DisposableList只接收實現了IDisposable接口的對象做為它的類型實參。這樣無論什麼時候,從DisposableList對象中移除一個對象時,那個對象的Dispose方法總是被調用。這使得您可以很容易的處理存儲在DisposableList對象中的所有對象。
下面代碼演示了DisposableList對象的使用:
public static void TestDisposableListCls() { DisposableList<StreamReader> dl = new DisposableList<StreamReader>(); // 創建一些測試對象. StreamReader tr1 = new StreamReader("c:\\boot.ini"); StreamReader tr2 = new StreamReader("c:\\autoexec.bat"); StreamReader tr3 = new StreamReader("c:\\config.sys"); // 在DisposableList內添加一些測試對象. dl.Add(tr1); dl.Insert(0, tr2); dl.Add(tr3); foreach(StreamReader sr in dl) { Console.WriteLine("sr.ReadLine() == " + sr.ReadLine()); } // 在元素從DisposableList被移除之前將調用它們的Dispose方法 dl.RemoveAt(0); dl.Remove(tr1); dl.Clear(); }
討論
where關鍵字用來約束一個類型參數只能接收滿足給定約束的實參。例如,DisposableList約束所有類型實參T必須實現IDisposable接口:
public class DisposableList<T> : IList<T>
where T : IDisposable
這意味著下面的代碼將成功編譯:
DisposableList<StreamReader> dl = new DisposableList<StreamReader>();
但下面的代碼不行:
DisposableList<string> dl = new DisposableList<string>();
這是因為string類型沒有實現IDisposable接口,而StreamReader類型實現了。
除了一個或多個指定接口需要被實現外,類型實參還允許其他約束。您可以強制類型實參繼承自一個指定類,如Textreader類:
public class DisposableList<T> : IList<T>
where T : System.IO.TextReader, IDisposable
您也可以決定是否類型實參僅為值類型或引用類型。下面的類聲明被約束為只使用值類型:
public class DisposableList<T> : IList<T>
where T : struct
這個類型聲明為只能使用引用類型:
public class DisposableList<T> : IList<T>
where T : class
另外,您也可能會需要一些類型實參實現了公有的默認構造方法:
public class DisposableList<T> : IList<T>
where T : IDisposable, new()
使用約束允許您編寫只接收部分類型實參的泛型類型。如果本節中的解決方案忽略了IDisposable約束,有可能會引發一個編譯錯誤。這是因為並非所有DisaposableList類的類型實參都實現了IDisposable接口。如果您跳過這個編譯期檢查,DisaposableList對象就可能會包含一個沒有公有無參的Dispose方法的對象。些例中將會引發一個運行期異常。
給泛型指定約束強制類的類型實參進行嚴格的類型檢查,並使得您在編譯期發現問題而不是運行期。