【问题标题】:typeof(T) vs <T>typeof(T) 与 <T>
【发布时间】:2023-03-08 10:10:01
【问题描述】:

在 .NET 中似乎有两种方法可以将类型传递给方法或类。第一种是通过泛型,我们将类型作为特殊参数传递。

如:

var list = new List<MyClass>();

另一种方法是显式使用typeof 运算符,例如:

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

我的问题是关于需要类型参数的方法的统一接口的差异。上面的语句为什么不能按如下方式进行?:

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

是因为编译器的行为方式需要两个语义差异吗?当编译器处理泛型参数时,它是否仅执行替换 ala lambda 演算?而typeof 样式方法需要Type 类的实际实例来推断属性和属性?

谢谢。

【问题讨论】:

  • 那些“特殊参数”被称为类型参数,你知道的:)
  • 想象一下广阔无垠的太平洋。 Type在日本,T在加利福尼亚。 T 到夏威夷的速度要快一千倍。
  • @Richard。我意识到。我不知道我为什么要这样表达。泛型在学术上被称为参数多态性,因此紧随其后的是类型参数。

标签: .net generics typeof


【解决方案1】:

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

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

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

【讨论】:

  • 多么明显的原因!我不敢相信我忽略了这一点!谢谢。
【解决方案2】:

考虑这个方法签名。

public object MyGetInstanceOfType(Type theType)

虽然可能会返回适当类型的实例,但编译器无法验证它...直到运行时才知道类型(在涉及编译器之后)。

对比一下:

public T MyGetInstanceOfType<T>()

这里编译器在每次调用者使用这个方法时都知道类型。它可以保证方法的返回,因为它知道所有调用的类型。

【讨论】:

    【解决方案3】:

    使用var list = new List&lt;MyClass&gt;();,List 类在编译时被告知它与特定类型相关联。然后编译器可以进行类型检查以确保只有 MyClass 的元素被添加到列表中。

    使用var pe = Expression.ParameterExpression(typeof(MyClass), "myinstance");,表达式在运行时被告知它正在使用什么类型的参数。编译器无法使用这种方法进行强类型检查。对于无法在编译时确定但这种情况很少见(尽管表达式树就是其中之一)的动态代码来说更好。

    【讨论】:

      【解决方案4】:

      从技术上讲,可以轻松创建通用版本,因为它可以调用采用以下类型的重载:

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

      不过,在这种情况下,使用泛型并不能为您带来太多收益。如果其中一个参数是 T 类型或返回值是 T 类型,那么您将获得基于指定类型参数的强类型。

      添加 Parameter 方法的通用版本不会使其或多或少成为强类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-23
        • 2020-12-03
        • 2011-09-23
        • 1970-01-01
        • 2022-12-18
        • 2016-01-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多