Общий способ обработки чисел без явного преобразования - PullRequest
2 голосов
/ 03 апреля 2012

У меня есть класс, который имеет свойство универсального типа, как указано ниже. Тип T может быть любым числом (short, int, float ...)

    public class EqualFilter <T> : Filter {
        private T _value;
        public override T Value {
        get {
            return _value;
        }
        set {
            if (!EqualityComparer<T>.Default.Equals(_value, value)) {
                _value = value;
                RaiseFilteringChanged();
            }
        }
    }
    .....
}

Теперь у меня есть класс клиента, у которого есть строка "String", которую нужно передать указанному выше установщику. Теперь во время установки значения в указанном выше установщике тип T уже определен во время выполнения, и я могу получить этот тип как Type T в моем клиенте. Можно ли преобразовать строку в соответствующий тип, как указано в EqualFilter, в клиентской программе? Нечто подобное, что не работает

Type T = filter.getFilterType();
filter.Value = (T) myTextBox.Text;

Приведенный ниже код работает, но он будет включать if-else для всех типов, которые могут быть числовыми.

Type T = filter.getFilterType();
if (T == typeof(int)) {
    filter.Value = Int32.Parse(myTextBox.Text);
} else if() {
....
}

Короче говоря, я не уверен, как лучше подойти к вопросу.

Ответы [ 3 ]

2 голосов
/ 10 апреля 2012

Похоже, вы делаете что-то похожее на привязку данных.Если все, что вас интересует, это работа со строками, вы можете ограничить универсальный тип IConvertible и вызвать метод Convert.ChangeType из специального метода-установщика, например:

public class EqualFilter<T> : Filter where T : IConvertible {

    // ... omitted Value property code ...

    public void SetValue(string value)
    {
        Value = (T)Convert.ChangeType(value, typeof(T));
    }

    // ...
}

Универсальный типограничение разрешает только те типы, с которыми Convert.ChangeType может работать.Помимо целочисленных типов и типов с плавающей запятой, это также позволяет использовать типы string, decimal и DateTime.Просто имейте в виду, что типы string не всегда могут быть точными при работе с типом double, поскольку могут быть ошибки округления и представления с плавающей запятой.Также могут быть другие исключения, которые вы можете захотеть отловить, чтобы сделать это более устойчивым (например, FormatException и OverflowException).

void Main()
{
    var a = new EqualFilter<int> { Value = 10 };
    var b = new EqualFilter<double> { Value = 20 };
    b.Value = Math.PI; // RaiseFilteringChanged called - no surprise
    b.SetValue(Math.PI.ToString()); // RaiseFilteringChanged called - surprised?
    Console.WriteLine(b.Value);
    b.SetValue("25");
    Console.WriteLine(b.Value);
    var c = new EqualFilter<DateTime> { Value = DateTime.Today };
    Console.WriteLine(c.Value);
    c.SetValue("12/23/2011");
    Console.WriteLine(c.Value);

    // compiler error object isn't an IConvertible:
    // var illegal = new EqualFilter<object>();
}

В этом случае обрабатывается большой оператор switchкаркасом в методе ChangeType.

Редактировать: Добавление вывода Console.WriteLine из моей версии кода выше (с переопределениями и использованием базового класса закомментировано):

3.14159265358979

25

4/10/2012 12:00:00

12/23/2011 12:00:00:00

1 голос
/ 03 апреля 2012

Вы можете попробовать следующее:

filter.Value = Convert.ChangeType(myTextBox.Text, filter.getFilterType());

Это не будет работать, если преобразование не определено.

Редактировать:

Я не заметил, что ваша собственность Value была родовой.Чтобы это работало, вы можете расширить объект фильтра следующим образом:

public object UnsafeValue
{
    set
    {
        Value = (T)value;
    }
}

и присвоить результат Convert.ChangeType этому свойству.

Каждый подход без изменения класса фильтра будетзадействуйте больше обобщений в иерархии вызовов или рефлексию.

0 голосов
/ 03 апреля 2012

Рассматривали ли вы создание определенного метода установки, как это:

public void setValue(object o){
   if (typeof(o) == typeof(Value)) {
       Value = (typeof(Value))o;
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...