简体   繁体   English

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

[英]How to restrict generic function to accept only some type of classes

I'm trying to do the following: 我正在尝试执行以下操作:

public class A
{
}

public class B
{
}

Somewhere along the project I want to have this: 在项目的某个地方我想要这个:

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;
    }
}

I've been trying: 我一直在努力:

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

but this gives me: 但这给了我:

The type class constraint 'B' must come before any other constraint. 类型类约束“B”必须在任何其他约束之前。

Can someone explain me how to make func accept only class A or class B? 有人可以解释我如何使func只接受A类或B类?

Exactly as it's described in the question, this job is better handled by overload resolution : 正如在问题中所描述的那样,这项工作可以通过重载解析来更好地处理:

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

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

}

But I understand that A and B may be placeholders for any number of types, and it could get tedious to account for them all. 但我知道A和B可能是任何类型的占位符,并且所有这些都可能变得乏味。 In that case, you'll need a common interface that's supported by each of your classes: 在这种情况下,您需要一个由您的每个类支持的通用接口:

interface IBase
{
    int x;
}

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

Note that at this point we still have no need of generics. 请注意,此时我们仍然不需要泛型。 Additionally, you may need to support a number of types that won't all fit together under a common interface. 此外,您可能需要支持许多类型,这些类型在通用接口下不能完全组合在一起。 In this case, still build the interface and put as many types with that interface as possible. 在这种情况下, 仍然构建接口并尽可能多地使用该接口。 If needed, build another interface for a few more types ... and so on... and then between interfaces and specific types you can handle things with overload resolution. 如果需要,为更多类型构建另一个接口......依此类推......然后在接口和特定类型之间,您可以处理具有重载决策的事物。

You need some kind of common base for both the classes, either have them implement the same interface as the below code or have them inherit from same class. 你需要为这两个类提供某种通用基础,要么让它们实现与下面代码相同的接口,要么让它们从同一个类继承。 You can not have a generic constrained to 2 types. 您不能将通用约束为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;
    }
}

The generics classes are just like any other class, you can't (and shouldn't) have multiple inheritance of classes, you can inherit one class and multiple interfaces. 泛型类与任何其他类一样,您不能(也不应该)具有多个类的继承,您可以继承一个类和多个接口。

in your case you should apply an interface on both classes and restrict the generics on that interface. 在您的情况下,您应该在两个类上应用接口并限制该接口上的泛型。

you can see some documentation in: Constraints on Type Parameters (C# Programming Guide) 你可以看到一些文档: 类型参数的约束(C#编程指南)

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;
    }
}

public T func<T>(T obj) where T: A, B this means T should extend both A and B , but multiple inheritance is not valid in C# ,so it won't work. public T func<T>(T obj) where T: A, B这意味着T应该扩展AB ,但是多重继承在C#无效,所以它不起作用。

You could do one of the following though : 您可以执行以下操作之一:

  1. you could make A and B have a common parent via an interface or an abstract class , but that would be code modification. 你可以通过interfaceabstract类使AB有一个共同的父,但这将是代码修改。

  2. since both A and B have a default no-arg constructor you could use where T: new() . 因为AB都有一个默认的无参数构造函数,你可以使用where T: new()

Also, you can not do obj.x = 100; 另外,你不能做obj.x = 100; as there is no way to guarantee that T will have a instance variable x . 因为没有办法保证T会有一个实例变量x

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM