Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

Как сделать cast с помощью переменной типа Type?

#c_sharp


Допустим где-то ранее по коду я сохранил тип переменной

Type type = typeof(Int32);


Теперь имея переменную value типа object мне нужно сделать cast c помощью моей type
как то так,

var i = (type)value;


но так не работает. Что можно сделать?

UPD
На всякий случай, так тоже не работает

var i = (type)Convert.ChangeType(value, type);


UPD2: по просьбе Pavel Mayorov добавляю в вопрос свой комментарий:

"...идея была такая: есть базовый абстрактный класс со свойством Object Value и со
свойством Type ValueType. Конкретный класс унаследовал этот абстрактный, назначал бы
нужный тип свойству ValueType, а свойству Value собственно значимую величину. Далее
при работе с коллекцией типов унаследованных от абстр.класса, можно было бы извлекать
значение Value нужного типа получая для этого тип из ValueType.".
    


Ответы

Ответ 1



Проведем небольшой тест Функция для каста: object CastTo(object inp) { return Convert.ChangeType(inp, typeof(T)); } Сам тест: void Main() { double d = 99.19; Console.WriteLine(d.GetType().Name); var intVal = CastTo(d); Console.WriteLine(intVal.GetType().Name); Console.WriteLine(d); Console.WriteLine(intVal); } Вывод в консоль Double Int32 99.19 99 UPD Если у вас под рукой нет Generic параметра, но вам нужно вызвать Generic метод, то вы можете сделать это через dynamic вот так: void Main() { object value = 100; CallGenericMethod(value); } public void CallGenericMethod(object inp) { GenericMethod((dynamic)inp); } public T GenericMethod(T inp) { Console.WriteLine($"Generic called! Parameter type {typeof(T).Name}, input type {inp.GetType().Name}"); return inp; } Вывод: Generic called! Parameter type Int32, input type Int32

Ответ 2



Компилятор не может работать с переменной неизвестного типа. У любой переменной должен быть известный на этапе компиляции тип данных. Но вам и не нужна переменная неизвестного типа: требуемый тип переменной определяется тем, как с ней предполагается работать. И его всегда можно определить. Как видно из ваших уточнений, вам нужно создать не просто переменную - а свойство в базовом классе. Эта задача решается проще чем вы думаете: достаточно сделать абстрактное свойство типа object. abstract class Foo { public abstract Type ValueType { get; } public abstract object UntypedValue { get; set; } } Нет никакой необходимости как-то дополнительно указывать что тип свойства UntypedValue - на самом деле ValueType (разве что можно написать об этом в комментарии). Ну а в производных классах просто перегружаем UntypedValue, делая так чтобы это свойство работало так как нам надо: class Foo : Foo { public override Type ValueType => typeof(T); public T Value { get; set; } public override object UntypedValue { get { return Value; } set { Value = (T)value; } } }

Комментариев нет:

Отправить комментарий