三元运算符语法选择接口的实现

时间:2014-04-16 09:09:00

标签: c# ternary-operator

我想知道为什么这行代码不能编译:

ILogStuff Logger = (_logMode) ? new LogToDisc() : new LogToConsole();

请注意,LogToDiscLogToConsole类都实现了ILogStuff,而_logMode是一个布尔变量。我得到的错误信息是:

  

错误3:无法确定条件表达式的类型,因为'xxx.LogToDisc'和'xxx.LogToConsole'之间没有隐式转换

但为什么要有一个呢?我错过了什么?

5 个答案:

答案 0 :(得分:15)

三元运算符没有可用的隐式转换。你需要通过三元运算符将返回的对象强制转换为ILogStuff,这在Eric Lippert对问题{(3}}

的回答中得到了很好的解释。
ILogStuff Logger = (_logMode) ? (ILogStuff) new LogToDisc() : (ILogStuff) new LogToConsole();

从C#语言规范的第7.13章开始:

  

?:运算符的第二个和第三个操作数控制条件表达式的类型。设X和Y是第二个和第三个操作数的类型。然后,

     
      
  • 如果X和Y是相同的类型,则这是条件表达式的类型。
  •   
  • 否则,如果从X到Y存在隐式转换(第6.1节),而不是从Y到X,则Y是条件表达式的类型。
  •   
  • 否则,如果从Y到X存在隐式转换(第6.1节),而不是从X到Y,则X是条件表达式的类型。
  •   
  • 否则,无法确定表达式类型,并发生编译时错误。
  •   

答案 1 :(得分:7)

你需要转换到界面:

ILogStuff Logger = (_logMode) ? (ILogStuff)new LogToDisc() : new LogToConsole();

规范描述了条件运算符的行为:

  

7.14条件运算符

     

?:运算符的第二个和第三个操作数x和y控制   条件表达式的类型。

     

如果x具有类型X且y具有类型   Y然后

     
  • 如果从X到Y存在隐式转换(第6.1节),但是   不是从Y到X,那么Y是条件表达式的类型。   
  • 如果存在从Y到X的隐式转换(第6.1节),而不是来自   X到Y,则X是条件表达式的类型。      
  • 否则,无法确定表达式类型,并且a   发生编译时错误。

LogToDiscLogToConsole之间没有任何方向的隐式转换,因此编译失败。如果您将其中一种类型修改为ILogStuff,则将存在来自其他类型的隐式转换。

答案 2 :(得分:3)

消息是正确的,这两种类型之间没有隐式转换,它们只是共享公共接口。但当然共享父母并不意味着投射的可能性,就像int并不是隐含的可转换为string一样,尽管两者都有共同的父母 - Object

三元运算符期望两个可能值的结果类型将相同 - 就在它们之间进行隐式转换的可能性而言。所以你必须告诉他,第一个返回值的类型为ILogStuff

ILogStuff Logger = (_logMode) ? (ILogStuff)new LogToDisc() : new LogToConsole();

然后,第二个可能的值是正确的 - 在LogToConsole类型和ILogStuff接口之间存在隐式转换。

答案 3 :(得分:3)

表达式必须返回两种实现的通用类型。通过将实例显式地转换为接口,表达式将编译:

ILogStuff Logger = (_logMode) ? 
    (ILogStuff)new LogToDisc() : 
    (ILogStuff)new LogToConsole();

答案 4 :(得分:0)

Adil提供了确定此行为的部分,但我想解释为什么这种行为是明智的。

bool ? val1 : val2

这是一个表达方式。表达式需要具有在编译时可确定的类型。这使它更快,并且更快地发现错误。

现在,如果:

val是MyObject1的一个实例,它扩展了SomeParent并实现了MyInterface
和val2是MyObject2的实例,它扩展SomeParent并实现MyInterface

我们如何确定此表达式的编译时类型?我们可以尝试在MyObject1MyObject2之间找到一种常见类型。什么是最明显的解决方案?你称之为SomeParent还是MyInterface?如果他们有2个接口,您会选择哪一个?

问题是这是一个烂摊子,并且需要一些非常人为的规则(实际上有更多的例子不太清楚),在一天结束时,它将不如当前定义那么直观。 / p>