17

我们可以在泛型类型参数上指定一个“派生自”约束,如下所示:

class Bar<T> where T : IFooGenerator

有没有办法指定NOT派生自?


我的用例:我有一堆可并行化的FooGenerators,每个都有相同的并行化代码,但我们不希望它们总是并行化。

public class FooGenerator : IFooGenerator
{
    public Foo GenerateFoo() { ... }
}

因此,我创建了一个通用容器类来并行生成 Foo:

public class ParallelFooGenerator<T> : IFooGenerator where T : IFooGenerator
{
    public Foo GenerateFoo()
    {
        //Call T.GenerateFoo() a bunch in parallel
    }
}

因为我想要FooGenerator并且ParallelFooGenerator<FooGenerator>可以互换,所以我制作ParallelFooGenerator : IFooGenerator. 但是,我显然不想ParallelFooGenerator<ParallelFooGenerator>合法。

那么,作为一个辅助问题,如果“非源自”约束是不可能的,是否有更好的设计方法?

4

3 回答 3

10

您可以使用以下内容:

public interface IFooGenerator
{
    Foo GenerateFoo();
}

interface ISerialFooGenerator : IFooGenerator { }

interface IParallelFooGenerator : IFooGenerator { }

public class FooGenerator : ISerialFooGenerator
{
    public Foo GenerateFoo()
    {
        //TODO
        return null;
    }
}

public class ParallelFooGenerator<T> : IParallelFooGenerator
    where T : ISerialFooGenerator, new()
{
    public Foo GenerateFoo()
    {
        //TODO
        return null;
    }
}
于 2012-06-25T18:25:32.793 回答
7

ParallelFooGenerator<ParallelFooGenerator>已经不可能了,因为ParallelFooGenerator是泛型类型并且您没有指定泛型参数。

例如,ParallelFooGenerator<ParallelFooGenerator<SomeFooGenerator>>有可能——允许这种类型真的那么糟糕吗?

于 2012-06-25T18:20:58.360 回答
4

简单回答是不。

长答案(仍然没有):

微软在他们对类型约束的解释中说得很好:“编译器必须保证它需要调用的运算符或方法将受到客户端代码可能指定的任何类型参数的支持。”

约束的根本目的不是禁止使用某些类型,而是让编译器知道支持哪些运算符或方法。但是,您可以检查一个类型是否在运行时实现/继承了特定的接口/基类并抛出异常。但是,这样一来,您将无法从智能感知中获得设计时错误。

我希望这有帮助。

于 2012-06-25T18:24:39.867 回答