2017-02-24 91 views
3

當我調用一個函數並用動態替換其中一個參數時,編譯器會將函數結果推斷爲動態。我不明白爲什麼會發生這種情況。帶動態功能參數的C#編譯器類型推理

例:推斷類型爲是動態的,所以這段代碼編譯,但當然在運行時失敗,RuntimeBinderException:

dynamic b = ""; 
var a = MethodWithoutOverloads("", b); 
a.DoesNotExist(); 

...

public string MethodWithoutOverloads(string a, string b) { ... } 

有人知道爲什麼類型推斷不是函數的返回類型?

編輯:編輯,以明確出現這種情況有沒有方法重載

回答

1

你是正確的,即編譯器可能原因的是,所有String.Format重載返回string,因此推斷a必須是一個字符串不管什麼b真的是。

事實是,編譯器不這樣做。它解決了一般情況,這很好,並且由於具有不同返回類型的重載在C#中是有效的,因此它將返回類型簡單地指定爲動態並允許運行時找出它。

回答您的具體問題,

public string MethodWithoutOverloads(string a, string b) { ... } 
dynamic a = ""; 
var result = MethodWithoutOverloads(a, a); // result is dynamic. 

讓我們來想象編譯器決定resultstring併發布到狂野的西部磁帶庫。然後,後來,你決定用下面的簽名添加過載:

public int MethodWithoutOverloads(int a, int b) { ... } 

現在,應該的result類型是什麼?而且,依賴result強制輸入到string的現有代碼會發生什麼變化?

string result = MethodWithoutOverloads(someDynamicVariable, someOtherDynamicVariable); 

語義完全變化;在消費者擁有一個安全的強類型變量之前,現在他突然有一個潛在的不安全隱式強制轉換,可能會在運行時崩潰。

0

因爲編譯器不知道哪個方法會在運行時被調用。

例如,你可以有兩種方法:

int MyMethod(int a) 
{ 
    return 5; 
} 

double MyMethod(string a) 
{ 
    return 6.0; 
} 

而且你寫下面的代碼:

dynamic myThing = 5; 
var myResult = MyMethod(myThing); 

考慮到我們已經明確表示myThing動態,這其類型是在運行時確定的,我們不知道哪個方法會被調用(如果有的話)。因此,我們也不知道返回類型。

+0

這種情況發生在我有一種方法時,即沒有歧義時。 String.Format不是一個好例子,但是當沒有歧義時我調用我自己的方法時類型推斷也失敗。 – Lev

+1

@Lev這是正確的。*技術上*編譯器或許能夠毫不含糊地將其弄清楚,但我認爲這需要更多的工作來獲得看似不大的收益。每當「動態」是表達式的一部分時,結果也將通過「動態」。如果你確定知道類型,只需使用變量類型明確而不是使用'var' – Rob

+0

好吧,所以基本上是「我們沒有對這種情況實現類型推斷」的情況...... – Lev

相關問題