1. 程式人生 > >“類型參數的約束”和“類型參數約束”有多大區別

“類型參數的約束”和“類型參數約束”有多大區別

gen ble table https 具體類 來源 個人簡介 per bject

雖然只相差一個字,但是區別還是挺大的。

先看看兩個詞的英文表述:constraints on type parameterstype parameters as constraints

其中後者最準確的翻譯應該是“(用)類型參數(作為)約束”,有些人也許會說你一個搞技術的也來這些標題黨的名堂,明明這麽多字,你非得省幾個,搞個危言聳聽,這還真不是,具體的慢慢往下看。

這篇博文主要來源於我對為了理解泛型中的where T : U這個東東找了一些資料

對這個內容解釋最權威的還是微軟的文檔,看這裏

我寫了個簡單的例子來驗證:

    public class Animal
    {
    }
    
public class Human : Animal { } public class AnimalList<T> where T : Animal { public void AddT(List<T> items) { } public void AddU<U>(List<U> items) where U : T { } }

調用的代碼:

            List<Animal> animals = new
List<Animal>(); animals.Add(new Human()); animals.Add(new Animal()); List<Human> humen = new List<Human>(); humen.Add(new Human()); //error CS1503: 參數 1: 無法從“ConsoleApp1.Animal”轉換為“ConsoleApp1.Human”
//humen.Add(new Animal()); var list = new AnimalList<Animal>(); list.AddT(animals); //error CS1503: 參數 1: 無法從“System.Collections.Generic.List<ConsoleApp1.Human>”轉換為“System.Collections.Generic.List<ConsoleApp1.Animal>” //list.AddT(humen); list.AddU(humen);

主要的區別就在AddT和AddU兩個函數上

where T : U的本質是用泛型參數來約束泛型參數,真繞口啊,其他的約束都是用具體類型來約束,碰到具體類型不好使的時候就要考慮用它了,不過用這種方法也有明顯的限制,

因為編譯器除了假設類型參數派生自System.Object以外,不能做出更強的假設,所以如果要在兩個類型參數之間強制繼承關系,可以將類型參數用作泛型類的約束。

最後再說說標題的事情,類型參數約束這個詞不是我取的,是Eric Lippert,如果對這個名字不熟悉,看看他的個人簡介吧

Eric Lippert designs programming languages at Facebook. Other notable work includes designing C# analyzers at Coverity, and developing the Visual Basic, VBScript, JScript and C# compilers at Microsoft.

據他說在C#編譯器項目組中他們就管這東東叫"type parameter constraints",直譯過來不就是“類型參數約束”,^_^

BTW:註意struct是隱式密封的,所以在泛型中涉及到派生什麽的時候都是說class(嚴格點說是引用類型),這點備忘下。

“類型參數的約束”和“類型參數約束”有多大區別