2011-04-01 113 views
6

在.NET中,似乎有两种方法可将类型传递给方法或类。第一种是通过泛型,我们在其中传递一个类型作为特殊参数。typeof(T)vs <T>

如:

var list = new List<MyClass>(); 

的另一种方法是显式使用typeof运营商如:

var pe = Expression.ParameterExpression(typeof(MyClass), "myinstance"); 

我的问题是关于在一个统一的接口,需要一个类型的方法的差异参数。为什么不能按照如下方式完成上述说明?:

var pe = Expression.ParameterExpression<MyClass>("myinstance"); 

是否因为编译器的行为方式需要两种语义差异?当编译器处理泛型参数时,它是否简单地执行替换ala lambda演算?鉴于typeof风格的方法需要Type类的实际实例来推断属性和属性?

谢谢。

+3

这些“特殊参数”被称为类型参数,所以你知道:) – 2011-04-01 18:06:12

+0

想象一下广阔的太平洋。 Type在日本,T在加利福尼亚州。 T比夏威夷快上千倍。 – 2011-04-01 19:13:22

+0

@Richard。我意识到。我不知道为什么我这样表达。泛型在学术上被称为参数多态性,所以类型参数紧随其后。 – 2011-04-01 19:35:23

回答

6

第一种方法允许您在运行时计算所需的类型。

Expression.ParameterExpression(CalculateType(), "myinstance"); 

就我个人而言,我不介意看到一个重载,它肯定会使编译时定义的类型的代码更清晰。

+0

什么是显而易见的原因!我无法相信我忽略了这一点!谢谢。 – 2011-04-01 19:33:21

0

从技术上讲,一个通用版本可以很容易地创建,因为它可以调用,需要一个类型,如过载:虽然

public static ParameterExpression Parameter<T>(string name) { 
    return Parameter(typeof(T), name); 
} 

在这种情况下,使用一个通用的不买你多少。如果其中一个参数的类型为T或者返回值的类型为T,那么您将根据指定的类型参数进行强类型化。

添加一个通用版本的Parameter方法并没有使其具有更强或更弱的类型。

2

With var list = new List<MyClass>(); List类在编译时被告知它被绑定到一个特定的类型。然后,编译器可以进行类型检查,以确保只有MyClass的元素被添加到列表中。

With var pe = Expression.ParameterExpression(typeof(MyClass), "myinstance");该表达式在运行时告诉它正在使用哪种类型的参数。编译器无法使用此方法进行强类型检查。在编译时无法确定事物的动态代码更好,但这些情况很少(尽管表达式树是其中之一)。

3

考虑这种方法签名。

public object MyGetInstanceOfType(Type theType) 

虽然可能返回相应类型的实例,编译器没有办法验证它... theType不知道(编译涉及好后),直到运行时。

与此不同的:

public T MyGetInstanceOfType<T>() 

这里编译器知道类型的每一个呼叫使用此方法时。它可以保证方法的返回,因为它知道所有调用的类型。