如何将泛型函数限制为仅接受某种类型的类

本文关键字:种类 类型 泛型 函数 | 更新日期: 2023-09-27 18:21:14

我正在尝试执行以下操作:

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

但这给了我:

类型类约束"B"必须位于任何其他约束之前。

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

如何将泛型函数限制为仅接受某种类型的类

正如问题中所述,此作业最好通过重载解析来处理:

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

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

你需要为

这两个类提供某种共同的基础,要么让它们实现与以下代码相同的接口,要么让它们从同一个类继承。不能将泛型限制为 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;
    }
}

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

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

您可以在以下位置查看一些文档:类型参数的约束(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这意味着

T应该同时扩展AB,但多重继承在C#中无效,因此它不起作用。

不过,您可以执行以下操作之一:

  1. 你可以通过interfaceabstract类创建AB有一个共同的父级,但这将是代码修改。

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

此外,您不能执行obj.x = 100;,因为无法保证T将具有实例变量x