【问题标题】:How do I add Generic constraints?如何添加通用约束?
【发布时间】:2014-11-18 10:59:13
【问题描述】:

我在C#中有以下情况:

class MyGenericClass<T>
{
    public void do()
    {
    }
}

class SpecificFooImpl : MyGenericClass<Foo>
{
     public void otherStuff()
     {
     }
}

现在我想编写一个只能返回MyGenericClass&lt;T&gt; 或特定实现的通用方法。我会写这样的:

var v1 = GetMyClass<MyGenericClass<Foo>>();
var v2 = GetMyClass<MyGenericClass<Bar>>();
var v3 = GetMyClass<SpecificFooImpl>();

我可以使用以下签名,但它对类型没有限制:

public T GetMyClass<T>();
//I don't want to write
//var v4 = GetMyClass<AnyOtherTypesWhichNotExtendMyGenericClass>();

有什么优雅的模式可以解决问题吗?

【问题讨论】:

标签: c# generics constraints


【解决方案1】:

在定义后添加 where : 子句,然后您可以定义应该遵守的内容。
我说过它必须是一个类,但你可以添加一个基类或接口作为约束。

class MyGenericClass<T> where T : class, IYourCommonInterface
{
    public void do()
    {
    }
}

参考文献
有关约束,请参阅 MSDN:http://msdn.microsoft.com/en-us/library/d5x73970.aspx

【讨论】:

  • 如何编写 where 子句?我找不到实现它的方法!
  • 复制我所拥有的,然后定义一个接口或另一个基类作为约束
【解决方案2】:

这有点棘手,因为您不能让类型约束保持打开状态 - 它必须是具体的。

所以你想做的是:

public T GetMyClass<T>() where T: MyGenericClass<>

不过,最接近的方法是包含第二个泛型类型,使MyGenericClass 具体化:

public T GetMyClass<T,T2>() where T: MyGenericClass<T2>

但是,这使得调用者需要了解太多关于实现的信息,尤其是在您使用 SpecificFooImpl 的地方。

相反,请考虑使用接口来移除您的内部泛型类型:

interface MyInterface
{
    void Stuff();
}

class MyGenericClass<T> : MyInterface
{
    public void Stuff()
    {
    }
}

那么你可以:

public T GetMyClass<T>() where T : MyInterface

【讨论】:

  • 所有需要的用法都可以工作(例如var v3 = GetMyClass&lt;SpecificFooImpl&gt;();),因为它们都派生自MyGenericClass&lt;T&gt;,现在实现了MyInterface
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多