2010-11-15 257 views
4

有人能解釋一下我下面的編譯器問題C#? :運營商

Error: Type of conditional expression cannot be determined because there is no implicit conversion between 'string' and 'int'

// WORKS 
string text = string.Format(
    "the id is {0}", _Obj.Id.ToString()); 

// WORKS, without implicit conversion <<< 
string text = string.Format(
    "the id is {0}", _Obj.Id); 

// WORKS 
string text = string.Format(
    "the id is {0}", (_Obj == null) ? "unknown" : _Obj.Id.ToString()); 

// NO WAY <<< 
string text = string.Format(
    "the id is {0}", (_Obj == null) ? "unknown" : _Obj.Id); 

在最後一個例子,不存在隱式轉換,以及。

+0

沒有................:0對不起。看到我的回答如下... – UpTheCreek 2010-11-15 11:43:09

回答

-1

在第一種情況下(即不起作用)如果_Obj == null,則返回string,否則返回int。這當然會導致一個問題,因爲你在這種情況下嘗試分配intstring text

+0

看到最後一個例子。 – serhio 2010-11-15 11:42:01

+0

害怕這是不正確的 - 問題是條件表達式必須解析爲單一類型,而不是兩種不同類型。與分配給字符串文本的String.Format的輸出無關。 – razlebe 2010-11-15 11:48:42

+0

最後一個例子是關於string.Format,與?:操作符無關。只是因爲?:指定兩個參數必須是相同的類型,或者它們之間存在隱式轉換的類型,並不意味着string.Format應該因爲相同的原因而失敗。因此string.Format返回一個字符串,而不管參數如何,並且將結果分配給字符串文本是沒有問題的。在?:的情況下,您返回一個字符串或一個int,並將其分配給字符串文本當然會生成一個編譯器異常。 – 2010-11-15 11:48:48

2

此表達式計算的類型是什麼?

(_Obj == null) ? "unknown" : _Obj.Id 
+0

string.Format接受任何類型作爲參數 – serhio 2010-11-15 11:43:47

+2

只需查看錶達式即可。如果編譯器無法確定要使用哪個超載,則無法編譯它。 – 2010-11-15 11:44:41

+0

@serhio:這是無關緊要的。一個條件表達式'q? x:y'要求'x'和'y'具有兼容的類型。 'string'和'int'不兼容。 – Joren 2010-11-15 11:46:23

10

該問題與您使用string.Format無關。問題是這樣的表達式:

(_Obj == null) ? "unknown" : _Obj.Id 

編譯器不能確定這個表達式的類型,因爲有intstring之間沒有隱式轉換。您已經找到該解決方案 - 調用ToString意味着無論哪種情況,表達式都會返回string。你可以修復它的另一種方法(但在這種情況下,因爲裝箱而效率稍低)是告訴編譯器明確指出如何執行轉換。例如,你可以使用一個顯式的object

(_Obj == null) ? "unknown" : (object)_Obj.Id 

你的第二個例子工程沒有進行明確的轉換,因爲string.Format期望一個object並且有一個隱式轉換從intobject

+0

我經常使用string.Format,因爲它不需要我使用ToString(),它會隱式地執行。作爲String.Format接受所有類型的參數,**編譯器可以將結果框爲Object **。 – serhio 2010-11-15 11:47:19

+3

@serhio:如果沒有'ToString',它必須轉換爲對象,因爲這是唯一的公共基類。編譯器不會自動爲你做這件事。理論上,只要y和z在'x?中不兼容,編譯器就可以轉換爲對象。 y:z',但即使在發生錯誤的情況下,代碼也會始終編譯。編譯器試圖警告你*嘿,這些對象是不同類型的,你確定要這樣做嗎?*如果你真的想要你仍然可以這樣做,但你需要對編譯器說*是的,我知道我在做什麼,只是施展對象 - 這將是好的*。 – 2010-11-15 11:52:34

+0

但我明白,這不是一個警告,而是一個錯誤。我希望這是一個警告,並評估我爲「對象」 – serhio 2010-11-15 11:57:05

0
"the id is {0}", (_Obj == null) ? "unknown" : _Obj.Id 

編譯器必須選擇任一挑string型或integer(猜測)其是不是可以通過默認交換反之亦然(沒有隱式轉換)

string text = string.Format("the id is {0}", _Obj.Id) 

string.Format需要object如精氨酸,所以沒有問題將Id(整數)轉換爲對象。

0

最後一個工程,因爲string.format將接受(string, object)

,因爲? :運營商需要匹配的類型第一個將無法正常工作

+0

我相信這個限制是沒有必要的。顯然,微軟並不認爲像我:) – serhio 2010-11-15 11:59:00

+2

@serhio:它不*必要*。這是一個設計選擇。要求條件運算符的操作數明確確定類型的好處是可以消除代碼分析中的困難和代價高昂的問題。缺點是用戶必須確保運算符具有不依賴表達式上下文的一致可推式類型。設計選擇始終是找到平衡衝突優先事項的妥協方案的結果。 – 2010-11-15 18:03:33

1

我認爲你需要閱讀MSDN: Conditional Operator

專門這一部分:

The second and third operands of the ?: operator control the type of the conditional expression. Let X and Y be the types of the second and third operands. Then,

If X and Y are the same type, then this is the type of the conditional expression. Otherwise, if an implicit conversion (Section 6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression. Otherwise, if an implicit conversion (Section 6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression. Otherwise, no expression type can be determined, and a compile-time error occurs.

+0

是的,但...我寧願:'否則,條件表達式的類型是** **對象** :) – serhio 2010-11-15 11:55:23

0

問題是

// WORKS, without implicit conversion 
string text = string.Format( 
    "the id is {0}", _Obj.Id); 

// NO WAY 
string text = string.Format( 
    "the id is {0}", (_Obj == null) ? "unknown" : _Obj.Id); 

是不一樣的!

試着想想術語

(_Obj == null) ? "unknown" : _Obj.Id); 

function int Eval(object obj) 
{ 
    if (obj == null) 
    { 
    return "unknown"; 
    } 
    else 
    { 
    return "1"; 
    } 
} 

這顯然是行不通的。所以整個事情與string.format無關。

+0

函數**對象** Eval(對象obj) – serhio 2010-11-15 11:50:33