好吧,我必須得到標題非常錯誤。更多的代碼,更少的字數:類型推斷推斷出類的範圍,但不包括方法,雖然它們是一樣的嗎?
public class Manager<T> where T : Control, new()
{
void Manage()
{
Do(t => IsVisible(t));
}
bool IsVisible(T t)
{
return t.Visible;
}
S Do<S>(Func<T, S> operation)
{
return operation(new T());
}
}
編譯器對Do
感到高興。它可以輕鬆推斷出T
類型。現在讓我說我有這個:
public static class Util
{
static void Manage()
{
Do(t => IsVisible(t)); //wiggly line here
}
static bool IsVisible<T>(T t) where T : Control
{
return t.Visible;
}
static S Do<S, T>(Func<T, S> operation) where T : Control, new()
{
return operation(new T());
}
}
編譯器希望類型現在明確鍵入。以下是我認爲:
在第一類中T
來自IsVisible
方法,其中有T
過載和T
被稱爲遍佈Manager
類,沒什麼大不了容易推斷出來。但在第二種情況下,T
被指定爲該方法的通用約束,可能難以推斷。好。
但是,這並不工作之一:
public static class Util
{
static void Manage()
{
Do(t => IsVisible(t)); //still wiggly line
}
static bool IsVisible(Control t)
{
return t.Visible;
}
static S Do<S, T>(Func<T, S> operation) where T : Control, new()
{
return operation(new T());
}
}
爲什麼不編譯器推斷在最後一種情況下
T
?更重要的是,最後一種情況與第一種情況有什麼不同?在第一種情況下,編譯器必須從
IsVisible
方法推斷它,然後一路回去檢查T
在IsVisible
中的類別,其中在最後一種情況下它在IsVisible
方法中容易獲得。所以我認爲第三種情況比第一種情況更容易。
Jon優秀的答案。對我很有啓發的真正答案是,在第一種情況下「T」不是被推斷出來的。我知道編譯器對第二種情況推斷類型有點苛刻,但我認爲如果從第三種情況推斷出類型,C#會更好。你的工作是受歡迎的。感謝你 – nawfal
喬恩,你不覺得它是C#的弱點,它不能從我的第三種情況推斷類型?如果重載'IsVisible',肯定會出現很多不明確的情況,但至少可以在編譯時導致模糊錯誤,就像它在其他情況下一樣 – nawfal
@nawfal:不是。鑑於類型推理規則已經非常複雜,我不想讓它們變得更復雜。如果你認爲你可以做得更好,我建議你試着寫出第三個案例需要編寫的規則。如果你能想出一個並不複雜的公式,我相信C#團隊很樂意聽到你的消息。 –