2017-10-04 94 views
-1

我有这样一段代码为什么?:操作符要求显式强制转换?

 StateMachine.State = string.IsNullOrEmpty(MyString) ? 
      (IState) StateMachine.StateA : StateMachine.StateB; 

我也可以写为

 if (string.IsNullOrEmpty(MyString)) 
      StateMachine.State = StateMachine.StateA; 
     else 
      StateMachine.State = StateMachine.StateB; 

StateIState类型和StateAStateB都实现IState的。

在第一个片段中,编译器要求显式强制转换,而在第二个片段中不需要。为什么在第一个例子中需要?编号: 建议的重复问题并不能完全覆盖我的问题。我的问题是关于对象和接口,而另一个问题是关于原始数据类型和常量。 特别是关于声明的quetzalcoatl的建议是非常有价值的。

阅读关于建议的重复问题的答案永远不会指向这个方向。

回答

3

发生这种情况时,在表达式x ? a : b A和B返回不同类型。

看看:

double a = 5; 
decimal b = 4; 
var z = x ? a : b; 

应该是什么Z的类型?即使A和B是某种兼容类型,例如intlong,编译器应该如何猜测返回的内容?结果应该是int还是long?

就你而言,最有可能的是,StateA的类型是“classA”,StateB的类型是“classB”。这两个类实现IState,所以简单的指派工作,但是当你把它放到?:操作符中时,编译器不能决定?:操作符的结果应该是classA还是classB

是的,我没有错:编译器甚至不考虑IState。为什么?因为classA和classB可能有许多其他常见接口或基本类型。他们可以使用实现IState,或者IEnumerable,或者.. object极端。编译器应该选择哪个通用基类?这很难决定,所以它不会猜测。

有一个非常简单的解决方案,除了明确的铸造,你已经发现你自己的。只需更改StateA和StateB字段/属性的返回类型即可。

现在,你可能有:

class StateMachine 
{ 
    public ClassA StateA {get .. } 
    public ClassB StateB {get .. } 
} 

以来都实现即将状态置,只是修改成:

class StateMachine 
{ 
    public IState StateA {get .. } 
    public IState StateB {get .. } 
} 

而且,后者的方式(提供国家实例只是接口),这可能更令人满意,因为如果StateMachine属性是用来选择状态的“存储库”,那么选择这些状态的代码位置可能不应该知道这些状态的确切实现类型 - 当然这不是必要的取决于你的设计。

+0

就是这样!一个非常好的建议将我的StateA和StateB的声明更改为IState。非常感谢你! – ffonz

相关问题