C#中静态泛型类的主要用途是什么?什么时候应该使用它们?哪些例子最能说明它们的用法?
例如
public static class Example{ public static ... }
由于您无法在其中定义扩展方法,因此它们的实用程序似乎有些受限.关于这个主题的网络参考很少,所以很明显没有很多人使用它们.这是一对夫妇: -
http://ayende.com/Blog/archive/2005/10/05/StaticGenericClass.aspx
静态泛型类作为字典
给出的答案摘要
关键问题似乎是" 静态泛型类与静态方法和非泛型静态类与静态泛型成员之间有什么区别?"
关于使用哪个的决定似乎围绕"类是否需要在内部存储特定于类型的状态?"
如果不需要特定于类型的内部存储,那么具有通用静态方法的静态非泛型类似乎更可取,因为调用语法更好并且您可以在其中定义扩展方法.
我使用静态泛型类来缓存反射重的代码.
假设我需要构建一个实例化对象的表达式树.我在类的静态构造函数中构建它一次,将其编译为lambda表达式,然后将其缓存在静态类的成员中.我经常不会公开评估这些课程 - 他们通常是其他课程的助手.通过以这种方式缓存我的表达式,我避免了在某种程度上缓存我的表达式的需要Dictionary
.
在BCL中有这种模式的一个例子.(DataRow
)扩展方法Field
和SetField
使用(私有)静态泛型类System.Data.DataRowExtensions+UnboxT
.用Reflector检查一下.
创建一个类static
不会添加任何功能 - 如果您打算在不实例化的情况下使用类,这只是一个方便的检查.这有几个用途......
您可以使用静态泛型类来解决限制:C#不允许部分特化.这意味着您必须指定所有类型参数或不指定.然而,这可能是不必要的冗长.
例如:
static class Converter { public TOut Convert(TIn x) {...} }
上一个类不允许类型推断,因为推理不适用于返回值.但是,如果不指定输入类型,也无法指定返回值类型,因为您无法进行部分特化.使用(可能是静态的)泛型类,您只能指定两种类型中的一种:
static class ConvertTo{ public TOut Convert (TIn x) {...} }
这样,您可以让类型推断适用于参数类型,并仅指定返回类型.
(虽然上面的情况是可以想象的,但它当然不要求泛型类是静态的).
其次,(正如Steven 首先指出的那样)每个构造类型都存在一个单独的静态字段,这使静态类成为存储类型或类型组合的额外信息的好地方.从本质上讲,它是一个半静态哈希表,可以键入类型.
键入类型的半静态查找表听起来有点小,但它实际上是一个非常非常有用的结构,因为它允许您存储昂贵的反射和代码生成结果,它们几乎可以自由查找(比字典便宜)因为它被JIT编入并且你避免调用.GetType()
).如果你正在进行元编程,这很棒!
例如,我在ValueUtils中使用它来存储生成的哈希函数:
//Hash any object: FieldwiseHasher.Hash(myCustomStructOrClass); //implementation: public static class FieldwiseHasher { public static int Hash(T val) { return FieldwiseHasher .Instance(val); } } public static class FieldwiseHasher { public static readonly Func Instance = CreateLambda().Compile(); //... }
静态泛型方法允许类型推断使用非常简单; 泛型类上的静态字段允许(元)数据的几乎无开销存储.如果像Dapper和PetaPoco这样的ORM 使用像这样的技术,那就不会让我感到惊讶; 但它对(de)序列化器也很有用.一个限制是你得到的开销很低,因为你绑定了编译时类型; 如果传递的对象实际上是子类的实例,则可能绑定到错误的类型 - 并添加检查以避免这种类型破坏低开销的好处.
泛型类型的静态字段特定于实际类型T.这意味着您可以在内部存储特定于类型的缓存.这可能是创建静态泛型类型的原因.这是一个(相当无用,但信息丰富)的例子:
public static TypeFactorywhere T : new() { // There is one slot per T. private static readonly object instance = new T(); public static object GetInstance() { return instance; } } string a = (string)TypeFactory .GetInstance(); int b = (int)TypeFactory .GetInstance();
我最近学到的静态泛型类的一种用法是在类的类级别上定义约束,然后约束适用于类的所有静态成员,我还学到了这是静态不允许的静态类定义扩展方法的泛型类.
例如,如果您要创建一个静态泛型类,并且您知道所有泛型类型都应该是IComparable(只是一个示例),那么您可以执行以下操作.
static class MyClasswhere T : IComparable { public static void DoSomething(T a, T b) { } public static void DoSomethingElse(T a, T b) { } }
请注意,我不需要将约束应用于所有成员,而只是在类级别.