【问题标题】:Why can't c# infer casting?为什么 c# 不能推断强制转换?
【发布时间】:2019-09-20 02:37:36
【问题描述】:

所以我最近第一次开始使用反射,发现 GetType() 可以知道对象的原始类型,即使它只是存储为对象。

foreach(object o in (IEnumerable) property.GetValue(element))
{
    List(o, verbose, int.MaxValue, subIncludes[attribute.Name], indents + 4);
}

所以这里 o 实际上是被传递到一个泛型方法中。发现传入后,o.GetType();返回实际的类类型而不是 System.Object 这让我感到惊讶。为了争论,假设类型是产品。所以如果类型是已知的,为什么有必要像Product p = (Product) o;那样将o转换为Product,而不是仅仅做Product p = o?既然类型是已知的,为什么不推断强制转换是期望的结果?

【问题讨论】:

  • 根本不清楚你在问什么。 "如果类型已知" -- 谁知道?具有object 类型参数的方法必须能够在不知道可能调用该方法的任何代码的情况下安全地编译。在该方法的上下文中,参数保证为object。仅仅因为一个调用者传递了Product,这并不意味着所有调用者都会传递Product。当o 仅声明为object 时,编译器无法保证Product p = o; 是安全的。
  • 说了这么多,a) 转换参数的通用方法几乎总是糟糕的设计,b) 从你的问题中甚至不清楚你在问什么样的推断。我试图猜测,但除非您为您的问题提供更好的清晰度,否则无法发布好的答案。确保其中包含一个minimal reproducible example,该minimal reproducible example清楚地显示您要问的是什么。
  • 您的变量o 引用了一个Product 对象。但是,编译器只知道变量o 是对象类型。您拥有引用Product 的变量只是您的执行代码。您的代码可以随时将任何对象(甚至一个值)分配给o。对于它的价值,如果你将o 输入为dynamic,你就是在告诉编译器,“相信我,我知道我在做什么”。那时你可以调用Product 的任何方法,但是编译器的成本不确定你在做什么是安全的
  • 为了更直接地解决它(在其他 cmets 中提出的观点),像 C#、Java 这样的语言,多态性是在运行时实现的,即在运行时只有系统会知道对象中包含哪种类型(想想多个类继承相同的接口)。这是这些语言的类型推断比函数式语言更弱的主要原因

标签: c# reflection casting type-conversion


【解决方案1】:

在编译时它不知道o 是什么。在这里使用不是Product 的东西是完全有效的。

您的主要问题 - ...instead of just doing Product p = o - 如果 Product 实现了隐式运算符怎么办?

public static implicit operator Product(object o)

然后,假设您想使用新的、宽松的转换语法 - Product p = o 运行时将不知道转换它的方式 - 使用隐式转换或您的转换。也许这就是不允许这种语法的原因。

【讨论】:

    【解决方案2】:

    强制转换是一个编译时特性。它告诉编译器你知道你在做什么。在运行时评估作为第二个示例的直接分配。

    【讨论】:

      猜你喜欢
      • 2012-03-06
      • 1970-01-01
      • 2014-01-02
      • 2017-02-19
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      • 2015-09-03
      • 2019-06-09
      相关资源
      最近更新 更多