C# 中的合取类型

本文关键字:取类型 | 更新日期: 2023-09-27 18:37:25

C# 中泛型类的一个优点是可以对类型进行约束,以便只接受满足多个约束的类型。例如:

public class Foo<T> where T : Bar, IBaz, IFoobar {
    public Foo (T value) {
        //initialize
    }
}

这意味着T只能与派生自三个描述类的类型统一。

使用方法时,也可以使方法泛型。但是,我想知道为什么不能在构造函数中指定这样的约束。例如:

public class Foo {
    public Foo (Bar & IBaz & IFoobar value) {
        //initialize (the "&" syntax is just an example)
    }
}

可以使类泛型,但如果只有构造函数将使用value并且类的其他方法不依赖于T,这可能会相当麻烦。有些问题甚至可能很难用泛型类来解决,例如,需要编写一个比较器SomeComparer<T,Q> : IComparer<Foo<T>,Foo<Q>>引入大量实际上根本不泛型的泛型类。

我不明白为什么没有实现这一点,因为类型系统可以轻松检查参数是否满足所有类型约束。

在 C# 语言规范中不定义合取类型的参数是什么?

C# 中的合取类型

该功能可能很有用,但尚未实现。C# 团队只有这么多时间,我想这从来没有成功过。有很多事情使这变得困难:假设您有Foo类和Foo<T>类,每个类都有非泛型和Foo<U>构造函数。如果你打电话给new Foo<int>(1),这是Foo..ctor<U>还是Foo<T>..ctorFoo<T>..ctor<U>new Foo<int><string>("")引用了吗?如果不引入一些新语法,并且以任何方式混淆我可以看到它正在完成,就无法完成它,所以也许最好不允许在构造函数上使用泛型。

您可以通过在非泛型类上编写泛型方法来解决此问题,例如

void Main()
{
    Foo foo = Foo.GetInstance(new BarBazAndFoobarImplementer());
}
public sealed class Foo {
    private Foo(Bar value) {
        this.Thing1 = value.BarProperty;
        this.Thing2 = ((IBaz)value).IBazProperty;
        this.Thing3 = ((IFoobar)value).IFoobarProperty;
    }
    public static Foo GetInstance<T>(T value) where T : Bar, IBaz, IFoobar {
        return new Foo(value);
    }
}

(这不会受到上述问题的困扰,因为您可以明确地调用Foo.GetInstance<U>(..)Foo<T>.GetInstance<U>(..)

可以完成这样操作的一种方法是使用私有构造函数和工厂方法:

public class Foo 
{
    public static Foo Create<T>(T value) where T : Bar, IBaz, IFoobar
    {
        return new Foo(value);
    }
    private Foo(Bar value)
    {
        // whatever
        // feel free to cast to IBaz or IFoobar as needed
    }
}

不能使用构造函数执行此操作,因为构造函数应该构造其类型的实例。你会用value做什么?也许将其存储在字段中,但是字段的类型是什么?

更好的方法可能是 Bar 或从 Bar 派生的类实现这两个接口。