是否可以将C#泛型方法类型参数约束为;可转让自;包含类';类型参数?
我怀疑答案是否定的,但我想知道是否有可能这样做:是否可以将C#泛型方法类型参数约束为;可转让自;包含类';类型参数?,c#,generics,type-constraints,C#,Generics,Type Constraints,我怀疑答案是否定的,但我想知道是否有可能这样做: public class MyGenericClass<TSomeClass> { public void MyGenericMethod<TSomeInterface>() // This doesn't compile. where TSomeClass : TSomeInterface { //... } } 这或多或少地强制了我想要的约束
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TSomeInterface>()
// This doesn't compile.
where TSomeClass : TSomeInterface
{
//...
}
}
这或多或少地强制了我想要的约束(即TSomeClass
必须继承自,或者在接口的情况下,实现,TSomeInterface
),但是调用它是非常笨拙的,因为我必须指定TIntermediateType
(尽管我确实希望它根据TSomeClass
进行计算):
var myGenericInstance=new MyGenericClass();
myGenericInstance.MyGenericMethod(TSomeClass,TSomeInterface);
此外,上述破解被破解,因为调用方理论上可以指定TSomeClass
的子类作为第一个类型参数,其中只有子类实现TSomeInterface
我之所以要这样做是因为我正在为WCF服务编写一个流畅的工厂模式,并且我希望防止调用方(在编译时)尝试使用服务类未实现的约定创建端点。我显然可以在运行时检查这一点(WCF实际上为我做了这一点),但我非常喜欢编译时检查
有没有更好/更优雅的方法来实现我在这里所追求的目标?我之所以能够理解为什么它无法编译,原因如下: 假设此程序编译:
class Program {
class Class1 { }
class Class2 { }
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TSomeInterface>() where TSomeClass : TSomeInterface {
}
}
static void Main(string[] args) {
var inst = new MyGenericClass<Class1>();
}
}
编译器会抱怨Class1
没有实现Class2
。但是,哪一行是错的?约束是在调用MyGenericMethod
时,但有问题的代码行是创建MyGenericClass
换句话说,哪一个得到了红色的曲线?如中所述,您不能在where
子句的左侧使用不是来自当前声明的类型参数
因此,正如w0lf在另一个问题中所建议的,您可以做的是在接口(而不是方法)声明中提供这两种类型:
public class MyGenericClass<TSomeClass, TSomeInterface> {
where TSomeClass : TSomeInterface
public void MyGenericMethod() // not so generic anymore :(
{
//...
}
}
可能您可以将其作为一个扩展方法,使其在用户面前看起来像一个实际的方法
这两者都不是您想要的,但可能比中间类型解决方案更好
至于为什么不呢?我猜这会使编译器变得复杂,而不会增加足够的值。这是一个例子。尽管C#和Java之间存在显著差异,但我认为她的结论也适用于此:
底线是类型下限的有用性
参数有些争议。它们会让人困惑,也许
甚至在用作泛型类的类型参数时也会产生误导。在…上
另一方面,泛型方法偶尔会从类型中获益
具有下限的参数。对于方法,为
通常会发现缺少下限类型参数。这样的
变通方法通常涉及静态泛型方法或更低的
绑定通配符
她还提供了一个很好的用例,请参见上面的链接。扩展方法提供了最好的解决方案,尽管它不能完全解决您的所有问题
public class MyGenericClass<TSomeClass>
{
}
public static class MyGenericClassExtensions
{
public static void MyGenericMethod<TSomeClass, TSomeInterface>(this MyGenericClass<TSomeClass> self)
where TSomeClass : TSomeInterface
{
//...
}
}
如果声明的类型参数MyGenericClass
与MyGenericMethod
的第一个类型参数不匹配,则将是编译错误
由于第一个类型参数可以通过
this
参数推断,因此编译器通常可以推断这两个类型参数,如果它们对方法有附加参数。这实际上是不可能的,因为您试图将泛型与运行时混合。不,我不是。我只是尝试应用一个C语言不允许的泛型约束(约束类型参数,使其成为包含类中类型参数的超类或实现接口)。在我看来,您尝试基于提供给方法的类型数据约束类泛型。如果要约束类泛型,则需要在类级别(逻辑上)执行此操作,否则JIT编译器无法创建具体的类。我正在尝试约束方法的参数,但我正在从正常顺序向后执行此操作。与其继承或实现TSomeClass
,我希望它被限制在TSomeClass
的基类和实现接口集合中。啊,我现在明白了,很抱歉:)在我的理想世界中,它当然是方法调用,就像您尝试这样做一样:varx=newlist();s、 增加(5)代码>。编译器假定声明正确,并且方法调用使用的参数无效+不过,我还是想了解一下语法。
static void Main(string[] args) {
var inst = new MyGenericClass<Class1>();
inst.MyGenericMethod<Class2>();
}
public class MyGenericClass<TSomeClass, TSomeInterface> {
where TSomeClass : TSomeInterface
public void MyGenericMethod() // not so generic anymore :(
{
//...
}
}
public class MyGenericClass<TSomeClass> {
public static void MyGenericMethod<TSomeClass, TSomeInterface>
(MyGenericClass<TSomeClass> that)
where TSomeClass : TSomeInterface
{
// use "that" instead of this
}
}
public class MyGenericClass<TSomeClass>
{
}
public static class MyGenericClassExtensions
{
public static void MyGenericMethod<TSomeClass, TSomeInterface>(this MyGenericClass<TSomeClass> self)
where TSomeClass : TSomeInterface
{
//...
}
}
var myGenericInstance = new MyGenericClass<TSomeClass>();
myGenericInstance.MyGenericMethod<TSomeClass, TSomeInterface>();