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

179
22 февраля 2018, 11:13

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

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.".

Answer 1

Проведем небольшой тест

Функция для каста:

object CastTo<T>(object inp)
{
    return Convert.ChangeType(inp, typeof(T));  
}

Сам тест:

void Main()
{
    double d = 99.19;
    Console.WriteLine(d.GetType().Name);
    var intVal = CastTo<int>(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>(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
Answer 2

Компилятор не может работать с переменной неизвестного типа. У любой переменной должен быть известный на этапе компиляции тип данных.

Но вам и не нужна переменная неизвестного типа: требуемый тип переменной определяется тем, как с ней предполагается работать. И его всегда можно определить.

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

abstract class Foo
{
    public abstract Type ValueType { get; }
    public abstract object UntypedValue { get; set; }
}

Нет никакой необходимости как-то дополнительно указывать что тип свойства UntypedValue - на самом деле ValueType (разве что можно написать об этом в комментарии).

Ну а в производных классах просто перегружаем UntypedValue, делая так чтобы это свойство работало так как нам надо:

class Foo<T> : Foo
{
    public override Type ValueType => typeof(T);
    public T Value { get; set; }
    public override object UntypedValue 
    {
        get { return Value; }
        set { Value = (T)value; }
    }
}
READ ALSO
Проблема с классом Random в C# [дубликат]

Проблема с классом Random в C# [дубликат]

На данный вопрос уже ответили:

272
Ошибка в коде js при котором некорректно работает alert

Ошибка в коде js при котором некорректно работает alert

Почему в видеоуроке от mailru написано $('a')

190
Вывести элементы массива каждый в новой строке

Вывести элементы массива каждый в новой строке

Вечер добрый! Есть массив arr=[{id:1, title:

241
Как удалить объекты в объекте?

Как удалить объекты в объекте?

Есть некий объект, внутри которого другие объекты доступны по ключам:

216