Можно ли привести переменную к типу, хранящемуся в другой переменной? - PullRequest
18 голосов
/ 21 января 2009

Вот что мне нужно сделать:

object foo = GetFoo();
Type t = typeof(BarType);
(foo as t).FunctionThatExistsInBarType();

Можно ли сделать что-то подобное?

Ответы [ 5 ]

20 голосов
/ 21 января 2009

Вы можете использовать метод Convert.ChangeType .

object foo = GetFoo(); 
Type t = typeof(string);
string bar = (string)Convert.ChangeType(foo, t);
14 голосов
/ 21 января 2009

Нет, вы не можете. C # не реализует утка, набрав .

Вы должны реализовать интерфейс и привести к нему.

(Однако есть попытки сделать это. Посмотрите на Duck Typing Project для примера.)

4 голосов
/ 21 января 2009

Ваш первоначальный вопрос был ошибочным в том, что вы просили рассматривать переменную как тип, который не известен во время компиляции, но учтите, что у вас есть строка, определенная слева, когда вы объявляете вашу переменную. C # с 3.5 статически типизирован.

Как только будет доступна динамика, вы можете сделать что-то вроде этого:

dynamic foo = GetFoo();
foo.FunctionThatExistsInBarType(); 

Если вы не знаете, что это за тип, но знаете, что он всегда будет поддерживать метод экземпляра FunctionThatExistsInBarType ();

на данный момент вы вынуждены использовать рефлексию (или код поколения, который на самом деле означает почти то же самое, но дороже, а потом быстрее).

// any of these can be determined at runtime
Type t = typeof(Bar);
string methodToCall = "FunctionThatExistsInBarType";
Type[] argumentTypes = new Type[0];
object[] arguments = new object[0];
object foo;
// invoke the method - 
// example ignores overloading and exception handling for brevity
// assumption: return type is void or you don't care about it
t.GetMethod(methodToCall, BindingFalgs.Public | BindingFlags.Instance)
    .Invoke(foo, arguments);
3 голосов
/ 11 февраля 2016

Поскольку динамика была добавлена ​​в c #, я думаю, что мы можем сделать это следующим образом:

class Program {
    static void Main(string[] args) {
        List<int> c = new List<int>(); 
        double i = 10.0;
        Type intType = typeof(int);
        c.Add(CastHelper.Cast(i, intType)); // works, no exception!
    }
}

class CastHelper {
    public static dynamic Cast(object src, Type t) {
        var castMethod = typeof(CastHelper).GetMethod("CastGeneric").MakeGenericMethod(t);
        return castMethod.Invoke(null, new[] { src });
    }
    public static T CastGeneric<T>(object src) {
        return (T)Convert.ChangeType(src, typeof(T));
    }
}
0 голосов
/ 23 июля 2013

При условии, что вы знаете все необходимые типы во время компиляции, печатание утки (вроде) возможно:

class BarFoo {}
class Foo {}
class Bar {}

class Program
{
    static void Main( )
    {
        var foo = new Foo( );
        var bar = new Bar( );
        var barfoo = new BarFoo( );

        Console.WriteLine(DoStuff(foo));
        Console.WriteLine(DoStuff(bar));
        Console.WriteLine(DoStuff(barfoo));

    }

    static string DoStuff(Foo foo) { return "DoStuff(Foo foo)"; }
    static string DoStuff(Bar bar) { return "DoStuff(Bar bar)"; }
    static string DoStuff(Base fb) { return "DoStuff(object fb)"; }
}

Выход:

Dostuff(Foo foo)
Dostuff(Bar bar);
DoStuff(object fb);

Если вы в конечном итоге реализуете много методов, которые в основном делают одно и то же, рассмотрите возможность реализации интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...