2017-10-04 50 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

相關問題