2009-01-21 85 views
17

这是我需要做的:是否可以将变量转换为存储在另一个变量中的类型?

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

能像这样做呢?

+0

你怎么知道这是你想上等号的最后一行左边的字符串你的榜样?换句话说,你打算如何处理bar,这意味着你不能使用“object bar =(object)foo;” ? – 2009-01-21 12:29:16

+0

我不这样做,字符串只是一个例子。我编辑了片段。 – 2009-01-21 12:58:02

回答

13

不,你不能。 C#不执行duck typing

您必须实现一个接口并对其进行转换。

(但也有尝试做到这一点。看看Duck Typing Project的例子。)

+0

是的,你可以。看看GvS的答案:-) – 2009-01-21 11:02:07

+1

你仍然需要实现接口(在这种情况下是IConvertible),并且知道要预先输入的类型。 – Quassnoi 2009-01-21 11:11:13

+0

我将这个答案标记为可接受的答案,因为我使用了Quassnoi的建议并实现了一个接口来投射它,但GvS和shuggycouk的答案也很棒。 – 2009-01-21 14:15:00

20

可以使用Convert.ChangeType方法。

object foo = GetFoo(); 
Type t = typeof(string); 
string bar = (string)Convert.ChangeType(foo, t); 
+6

仅当对象实现IConvertible时才有用 – Quassnoi 2009-01-21 11:03:27

4

你原来的问题是有缺陷的,你问治疗变量未在编译时已知的,但请注意,您对左侧定义字符串时,你声明你的变量类型。 C#的3.5是静态类型。

一旦动态可用,你可以做这样的事情:

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

因为当你不知道类型是什么,但你知道它会一直支持实例方法FunctionThatExistsInBarType();现在你不得不使用反射(或者代码gen,这些代码真的相当于一样的东西,但是前面更加昂贵,后面会更快)。

// 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); 
0

只要你在编译时知道所有需要的类型,duck typing是(在某种程度上)可能:

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); 

如果你最终实现了很多基本上完全相同的方法,考虑实现一个接口。

2

由于动态加入到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)); 
    } 
} 
相关问题