什麼是靜態的關鍵用途 C#中的泛型類?他們應該在什麼時候使用 ?哪些例子最能說明 的使用?
我認爲一般來說,你應該避免在靜態類上創建類型參數,否則你不能依賴類型推斷來使你的客戶端代碼更加簡潔。
舉一個具體的例子,假設你正在編寫一個靜態工具類來處理List上的操作。你可以寫兩種方法:
// static class with generics
public static class ListOps<T>
{
public static List<T> Filter(List<T> list, Func<T, bool> predicate) { ... }
public static List<U> Map<U>(List<T> list, Func<T, U> convertor) { ... }
public static U Fold<U>(List<T> list, U seed, Func<T, U> aggregator) { ... }
}
// vanilla static class
public static class ListOps
{
public static List<T> Filter<T>(List<T> list, Func<T, bool> predicate) { ... }
public static List<U> Map<T, U>(List<T> list, Func<T, U> convertor) { ... }
public static U Fold<T, U>(List<T> list, U seed, Func<T, U> aggregator) { ... }
}
但類是等價的,但哪一個更容易使用?比較:
// generic static class
List<int> numbers = Enumerable.Range(0, 100).ToList();
List<int> evens = ListOps<int>.Filter(numbers, x => x % 2 = 0);
List<string> numberString = ListOps<int>.Map(numbers, x => x.ToString());
int sumOfSquares = ListOps<int>.Fold(numbers, 0, (acc, x) => acc + x*x);
// vanilla static class
List<int> numbers = Enumerable.Range(0, 100).ToList();
List<int> evens = ListOps.Filter(numbers, x => x % 2 = 0);
List<string> numberString = ListOps.Map(numbers, x => x.ToString());
int sumOfSquares = ListOps.Fold(numbers, 0, (acc, x) => acc + b * b);
在我看來,笨重笨拙。由於類型推斷,vanilla類的定義稍大,但客戶端代碼更易於閱讀。
在最糟糕的情況下,C#無法推斷出類型,您必須手動指定它們。你願意寫ListOps<A>.Map<B>(...)
還是ListOps.Map<A, B>(...)
?我偏好後者。
上述策略效果尤其好,當你的靜態類持有沒有可變狀態,或它的可變的狀態是在編譯時知道。
如果靜態類保持其類型在編譯時未確定的可變狀態,那麼您可能有一個具有泛型參數的靜態類的用例。希望這些場合少之又少,但是當它發生時,你會很高興C#支持這種功能。
將靜態lambda表達式創建構造函數的示例作爲答案的一部分將是有益的。 – Jim 2016-07-12 07:16:25