如何限制泛型函数只接受某种类型的类

时间:2015-11-08 04:52:01

标签: c# generics

我试图执行以下操作:

public class A
{
}

public class B
{
}

在项目的某个地方我想要这个:

public class C
{
    public T func<T>(T obj) [where T can be either of class A or class B]
    {
        obj.x = 100;

        return obj;
    }
}

我一直在尝试:

public T func<T>(T obj) where T: A, B

但是这给了我:

  

类型类约束&#39; B&#39;必须先于任何其他约束。

有人可以解释我如何让func只接受A类或B类?

5 个答案:

答案 0 :(得分:5)

正如问题中描述的那样,重载决议可以更好地处理这项工作:

public class C
{
    public A func(A obj)
    {
        obj.x = 100;   
        return obj;
    }

    public B func(B obj)
    {
        obj.x = 100;   
        return obj;
    }

}

但是我知道A和B可能是任何类型的占位符,并且所有这些都可能变得乏味。在这种情况下,您需要一个由您的每个类支持的通用接口:

interface IBase
{
    int x;
}

public class C
{
    public IBase func(IBase obj)
    {
        obj.x = 100;   
        return obj;
    }
}

请注意,此时我们仍然不需要泛型。此外,您可能需要支持许多类型,这些类型在通用接口下不能完全组合在一起。在这种情况下,仍构建接口,并尽可能多地使用该接口。如果需要,为更多类型构建另一个接口......依此类推......然后在接口和特定类型之间,您可以处理具有重载分辨率的事物。

答案 1 :(得分:2)

您需要为这两个类提供某种通用基础,要么让它们实现与下面代码相同的接口,要么让它们从同一个类继承。您不能将通用约束为2种类型。

public interface IFooBar
{
    void DoThis();
}

public class Foo : IFooBar
{
    public void DoThis()
    {
        //Do something
    }
}

public class Bar : IFooBar
{
    public void DoThis()
    {
        //Do something
    }
}

public class C
{
    public T func<T>(T obj) where T : IFooBar
    {
        obj.DoThis();
        return obj;
    }
}

答案 2 :(得分:0)

泛型类就像任何其他类一样,你不能(也不应该)有多个类的继承,你可以继承一个类和多个接口。

在您的情况下,您应该在两个类上应用接口并限制该接口上的泛型。

你可以看到一些文档: Constraints on Type Parameters (C# Programming Guide)

答案 3 :(得分:0)

interface IMarkerInterface{} // there is a such pattern called marker  
                             // interface . No need to have methods if there 
                            // is no need for, A and B can just implement it 

public class A: IMarkerInterface
{
}

public class B: IMarkerInterface
{
}

public class C
{
    public T func<T>(T obj).Where T:IMarkerInterface
    {
        obj.x = 100;
        return obj;
    }
}

答案 4 :(得分:0)

public T func<T>(T obj) where T: A, B这意味着T应该同时延伸AB,但多重继承在C#中无效,因此它赢了工作

您可以执行以下操作之一:

  1. 您可以通过AB类使interfaceabstract拥有共同的父级,但这将是代码修改。

  2. 由于AB都有默认的无参数构造函数,因此您可以使用where T: new()

  3. 另外,由于无法保证obj.x = 100;具有实例变量T,因此无法执行x