这是好奇心和部分原因,因为我只是想尝试使用它。如果您具有以下定义,则编译器不允许这样做,因为它表示已定义成员。不允许泛型类型参数的独占重载的原因是什么?
void Get<T>() where T: struct {}
void Get<T>() where T: class {}
在我看来,这没有固有的问题。有人可能会争辩说,在定义重叠的情况下,编制者应该选择哪个并不总是很清楚(但是普通分辨率似乎是最具体的匹配)。
有人可以帮助我理解或指出资源禁止这种情况的原因是什么?
答案 0 :(得分:9)
Eric Lippert已经在关于通用约束和方法签名的博客文章中回答了这个问题:http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx
泛型类型的约束不是CLR中方法签名的一部分,因此您不能有两种方法仅在泛型类型约束方面有所不同。如果没有CLR支持,让C#以一种与其他.NET语言兼容的合理方式支持这些将是非常繁琐的。
答案 1 :(得分:1)
struct
对Nullable<T>
的约束是恕我直言,真的很不幸。像Nullable<String>
或Nullable<Nullable<Nullable<int>>>
这样的东西可能会浪费,但那又怎样呢?将前者作为其内容;取消将其作为内容取消,如果内容为非空,则设置HasValue
。如果所有nullables报告int
,则将前者列为HasValue
,并且当取消装箱时,如果内容为非null,则设置所有嵌套项目的HasValue
。
否则,我建议您创建一个类型为T
的静态泛型类,其中包含一个委托属性,该属性接受T
作为参数。该属性应返回应初始化的私有字段的内容,以指向将检查T
类型的方法,并将委托设置为struct
或class
版本为合适的。
这是我正在谈论的一个样本;这个使用各种接口约束而不是结构/类约束,但同样的原则可以同样有效地使用。
static class _FooDispatcher<T> { public static Action<T> Foo = setupFoo; static void doFooWithIGoodFoo<TT>(TT param) where TT : IGoodFoo { Console.WriteLine("Dispatching as IGoodFoo with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference"); param.Foo(); } static void doFooWithIOkayFoo<TT>(TT param) where TT : IOkayFoo { Console.WriteLine("Dispatching as IOkayFoo with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference"); param.Foo(); } static void doFooSomehow<TT>(TT param) { Console.WriteLine("Nothing exciting with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference"); } static void setupFoo(T param) { System.Reflection.MethodInfo mi; if (typeof(IGoodFoo).IsAssignableFrom(typeof(T))) mi = typeof(_FooDispatcher<T>).GetMethod("doFooWithIGoodFoo", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); else if (typeof(IOkayFoo).IsAssignableFrom(typeof(T))) mi = typeof(_FooDispatcher<T>).GetMethod("doFooWithIOkayFoo", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); else mi = typeof(_FooDispatcher<T>).GetMethod("doFooSomehow", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); Foo = (Action<T>)(@Delegate.CreateDelegate(typeof(Action<T>), mi.MakeGenericMethod(typeof(T)))); Foo(param); } }