这个问题已经在这里有了答案 :
8年前关闭。
可能重复: 条件运算符不能隐式转换吗? 为什么null需要在此处强制转换为显式类型?
我进行了搜索,但没有找到关于以下原因的良好解释。 我有两个具有共同接口的类,并且尝试使用如下三元运算符初始化此接口类型的实例,但这无法编译,且错误为“无法确定条件表达式的类型,因为之间没有隐式转换’xxx.Class1’和’xxx.Class2’:
public ConsoleLogger : ILogger { .... } public SuppressLogger : ILogger { .... } static void Main(string[] args) { ..... // The following creates the compile error ILogger logger = suppressLogging ? new SuppressLogger() : new ConsoleLogger(); }
如果我将第一个conditioin显式转换为我的界面,则此方法有效:
ILogger logger = suppressLogging ? ((ILogger)new SuppressLogger()) : new ConsoleLogger();
很明显,我总是可以做到这一点:
ILogger logger; if (suppressLogging) { logger = new SuppressLogger(); } else { logger = new ConsoleLogger(); }
替代方法很好,但是我不能完全理解为什么第一个选项会因隐式转换错误而失败,因为在我看来,这两个类都是ILogger类型,并且我并不是真正地在进行转换(隐式或显式)。 )。我确定这可能是静态语言编译问题,但我想了解发生了什么。
这是C#的两个特征融合的结果。
首先是C#永远不会为您“神奇”一个类型。如果C#必须从一组给定类型中确定“最佳”类型,则它总是选择您提供的一种类型。它从未说过:“您给我的类型都不是最好的类型;由于您给我的选择都是不好的,所以我将挑选一些您没有给我的随机选择。”
第二个是从C#原因 里面 到 外面 。我们不会说“哦,我看到您正在尝试将条件运算符结果分配给ILogger;让我确保两个分支都起作用。” 相反的情况发生了:C#说“让我确定两个分支返回的最佳类型,并验证最佳类型是否可以转换为目标类型。”
第二条规则是明智的,因为 目标类型可能是我们要确定的目标类型。 当您说D d = b ? c : a;清楚目标类型是什么时。但是,假设您打电话给您M(b?c:a)?M可能有一百种不同的重载,每种重载都具有形式参数的不同类型!我们必须确定参数的类型,然后丢弃M的重载,这是不适用的,因为参数类型与形式参数不兼容。我们不会走另一条路。
D d = b ? c : a;
M(b?c:a)
考虑如果我们采取其他方式会发生什么:
M1( b1 ? M2( b3 ? M4( ) : M5 ( ) ) : M6 ( b7 ? M8() : M9() ) );
假设每个M1,M2和M6都有一百个过载。你是做什么?您是否说好,如果这是M1(Foo),则M2(…)和M6(…)必须都可以转换为Foo。是吗 让我们找出答案。M2的过载是多少?有一百种可能性。让我们看看它们中的每一个是否都可以从M4和M5的返回类型转换而来…好吧,我们已经尝试了所有这些,所以我们找到了一个可以工作的M2。现在M6呢?如果我们发现“最佳” M2与“最佳” M6不兼容怎么办?我们是否应该回溯并继续重试所有100 x 100的可能性,直到找到兼容的对?问题变得越来越严重。
我们 这样做的 原因是lambda,因此涉及lambda的重载解析至少在C#中为NP-HARD。那很不好 我们宁愿不为编译器添加更多的NP- HARD问题来解决。
您还可以在该语言的其他位置看到正在运行的第一条规则。例如,如果您说: ILogger[] loggers = new[] { consoleLogger, suppressLogger };您将收到类似的错误;推断的数组元素类型必须是给定类型表达式的 最佳类型 。如果无法从中确定最佳类型,我们不会尝试查找您没有给我们的类型。
ILogger[] loggers = new[] { consoleLogger, suppressLogger };
类型推断也一样。如果你说:
void M<T>(T t1, T t2) { ... } ... M(consoleLogger, suppressLogger);
这样就不会推断T为ILogger;这将是一个错误。在提供的参数类型中,T被推断为最佳类型,并且在它们之间没有最佳类型。
有关此设计决策如何影响条件运算符的行为的更多详细信息,请参阅我关于该主题的系列文章。
如果您对为什么“从外部到内部”有效的过载解析是NP- HARD感兴趣,请参阅本文。