2

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# 语言规范中不定义合取类型的论点是什么?

4

2 回答 2

1

该功能可能有用,但尚未实现。C# 团队只有这么多时间,我想这只是从未成功过。有很多事情使这变得困难:假设您有FooFoo<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>(..)and Foo<T>.GetInstance<U>(..)

于 2013-10-30T15:00:37.477 回答
1

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

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两个接口的类。

于 2013-10-30T15:05:50.127 回答