程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#函數式程序設計之泛型(下)

C#函數式程序設計之泛型(下)

編輯:C#入門知識

C#函數式程序設計之約束類型   每當使用泛型類型時,可以通過where字句對泛型添加約束:     static void OutputValue<T>(T value) where T : ListItem<string> {       Console.WriteLine("String list value: {0}", value.Value); } 這個例子直觀地聲明了一個約束:類型T必須與ListItem<string>相匹配。泛型類型約束T:X表示T可以是X、X的派生對象或X的實現(假如X是一個接口)。換言之,假如類型T的一個實例為t,則可以把它賦給一個變量:X x=t;   約束可以使用具體的類型,但是在這些情形下,類型不可以是密封的。有幾個特殊的關鍵字可以取代或補充類型聲明符。關鍵字class表示此類型必須是一個引用類型,而struct表示它必須是一個值類型。當new()與class或者任何具體類型一起使用時,可以給這個類型定義一個默認的構造函數。   約束的最後一個應用是定義兩個類型參數的關系。例如,對於類型參數的T和U,約束T:U表示T必須與U相容。   使用約束時,有一點必須記住:泛型的基本作用是提供一個類型安全的方法,使代碼可以處理不同類型的數據。約束用得越多,則離這個思想越遠,因為約束降低了靈活性。   C#函數式程序設計之其他泛型類型   除了方法與類外,結構體、委托和接口也可以使用類型參數。結構體和接口使用類型參數是顯而易見的,其用法與類相似:   public struct MyPoint<T> where T : struct {       public MyPoint(T x, T y)       {             this.x = x;             this.y = y;       }         private readonly T x;       public T X       {            get            {                 return x;            }       }         private readonly T y;       public T Y       {            get            {                 return y;            }       }         public interface IListItem<T>       {            T Value { get; }             ListItem<T> Prepend(T value);        } } 即使是委托,其用法也絲毫沒有令人吃驚的地方:     public delegate R CreateDelegate<T, R>(T param); public class ParameterFactory<T, R> {       CreateDelegate<T, R> createDelegate;       public ParameterFactory(CreateDelegate<T, R> createDelegate)       {            this.createDelegate = createDelegate;       } } 使用了泛型後,這些委托幾乎可以代表任何函數。   C#函數式程序設計之協變與逆變   如果一個操作保留了類型原來的順序,則成為協變,如果顛倒它們的順序,則稱為逆變。所謂的類型順序是指:通用類型的順序值比專用類型的順序值強。   下面這個例子說明C#支持協變,首先定義一個對象數組:     object[] objects = new object[3]; objects[0] = new object(); objects[1]="Just a string"; objects[2]=10; 可以把不同的值插入到這個數組中,因為所有數據最終都是派生自.NET中的Object類型。換言之,Object是一個非常通用的類型,即它是一個強類型。接下來說明.NET支持協變,它把一個弱類型的值賦給強類型的變量:     string[] stringsTest = new string[] { "one", "two", "three" }; objects = stringsTest; 變量objects屬於object[]類型,它可以保存實際類型為string[]的值。仔細想想,我們希望如此,但是結果不是這樣的,畢竟,雖然string派生自object,但是string[]並不是派生自object[]。盡管如此,由於本例中C#支持協變,這個賦值是可行的。   說明逆變思想需要一個比較復雜的例子:     public class Person:IPerson {     public Person() { } }   public class Woman : Person {     public Woman() { } } Woman是從Person派生出來的類,現在分析如下兩個函數:     static void WorkWithPerson(Person person) { }   static void WorkWithWonman(Woman woman) { } 其中一個函數作用於Woman類,另一個函數比較通用,作用於Person類。從Woman類可以定義以下兩個委托和函數:     delegate void AcceptWomanDelegate(Woman person);   static void DoWork(Woman woman, AcceptWomanDelegate acceptWoman) {      acceptWoman(woman); } DoWork函數接受一個Woman參數和一個函數引用,後者也接受一個Woman參數。DoWork函數把Woman實例傳遞給委托。元素類型大小為:Person比Woman強,WorkWithPerson比WorkWithWoman強,為了應用逆變,在此認為WorkWithPerson比AcceptWomanDelegate強,看以下三行代碼:     Woman woman = new Woman(); DoWork(woman, WorkWithWonman); DoWork(woman, WorkWithPerson); 首先創建一個Woman實例,然後調用DoWork函數,把Woman實例和WorkWithWoman方法的引用地址傳遞給DoWork。後者顯然是與委托類型AcceptWomanDelegate相容——兩者都只有一個Woman類型參數,沒有返回值。但第三行代碼有點怪,根據AcceptWomanDelegate的要求,WorkWithPerson方法接受一個Person參數,而不是一個Woman參數。雖然如此,WorkWithPerson還是與委托類型相容,這是逆變的緣故。   因此,在委托類型下,強類型可以保存在弱類型的變量中。   變異也能應用在泛型中。如下代碼:     List<object> objectList = new List<object>(); List<string> stringList = new List<string>(); objectList = stringList;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved