gpt4 book ai didi

c# - 抽象基类/派生类的空合并问题

转载 作者:可可西里 更新时间:2023-11-01 07:50:38 26 4
gpt4 key购买 nike

为什么 C# 空合并运算符无法解决这个问题?

  Cat c = new Cat();
Dog d = null;

Animal a = d ?? c;

这会报错

运算符 ??不能应用于 Dog 和 Cat 类型的操作数

考虑到以下编译,这看起来很奇怪。

Animal a = d;
a = c;

上下文代码如下:

public abstract class Animal
{
public virtual void MakeNoise()
{
Console.WriteLine("noise");
}
}

public class Dog : Animal
{
public override void MakeNoise()
{
Console.WriteLine("wuff");
}
}

public class Cat : Animal
{
public override void MakeNoise()
{
Console.WriteLine("miaow");
}
}

最佳答案

C# 的微妙设计规则之一是 C# 从不推断不在表达式开头的类型。因为 Animal 不在表达式 d ?? cAnimal 类型不是一个选择。

此原则适用于 C# 推断类型的所有地方。例如:

var x = new[] { dog1, dog2, dog3, dog4, cat }; // Error

编译器不会说“这一定是一个动物数组”,它会说“我认为你犯了一个错误”。

这就是更通用的设计规则的特定版本,即“当程序看起来不明确时给出错误,而不是做出可能错误的猜测”。

另一个在这里发挥作用的设计规则是:从内到外而不是从外到内推理类型。也就是说,您应该能够通过查看表达式的部分 来计算出表达式中所有内容的类型,而无需查看其上下文。在您的示例中,Animal 来自 ?? 表达式之外;我们应该能够弄清楚 ?? 表达式的类型是什么,然后问“这个类型与上下文兼容吗?”而不是反过来说“这是上下文——现在计算出 ?? 表达式的类型。”

这个规则是有道理的,因为上下文经常是不清楚的。在您的情况下,上下文非常清楚;事物被分配给 Animal。但是关于:

var x = a ?? b;

现在正在推断 x 的类型。我们不知道上下文的类型,因为这就是我们正在研究的内容。或者

M(a ?? b)

M 可能有两打重载,我们需要根据参数的类型知道选择哪一个。很难以另一种方式推理并说“上下文可能是这十几种事物之一;在每个上下文中评估 a??b 并计算出它的类型”。

lambda 违反了该规则, 根据其上下文对其进行了分析。让代码既正确又高效是非常困难的;它花了我一年工作的大部分时间。编译器团队可以通过不在不需要的地方承担费用来更快更好地完成更多功能。

关于c# - 抽象基类/派生类的空合并问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19974664/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com