我可以在C#泛型约束中指定“超类型”关系吗?

时间:2009-07-27 14:09:14

标签: c# generics delegates constraints

我有一个带有Equals方法的集合类,我希望在方法中传递每个项目之间的相等性检查。此外,我想允许委托类型操作T的超类以及T本身:

public delegate bool EqualityComparer<T>(T x, T y);

public class Collection<T>
{
    //...

    public bool Equals<U>(Collection<T> other, EqualityComparer<U> eq) where T : U
    {
        // code using eq delegate to test equality between
        // members of this and other collection
    }
}

不幸的是,编译器对此进行了抨击('Collection.Equals()'没有定义类型参数'T')。有没有办法指定这种类型的约束/操作?

3 个答案:

答案 0 :(得分:4)

不,我担心你不能指定这样的约束。 (我偶尔也想要它。)

可以在非泛型类中编写一个带有两个类型参数的静态泛型方法,但是:

public delegate bool EqualityComparer<T>(T x, T y);

public class Collection
{
    public static Equals<T, U>(Collection<T> first,
                               Collection<T> second,
                               EqualityComparer<U> comparer) where T : U
    {

    }
}

如果您愿意,甚至可以在泛型类上调用该实例方法:

// Implementing the static method:
return first.Equals(second, new EqualityComparer<T>(comparer));

集合的实例方法就是:

public bool Equals(Collection<T> other, EqualityComparer<T> eq)
{
    // ...
}

这使用了从C#2开始创建代表的可用性。

答案 1 :(得分:1)

正如Jon所说,你不能以这种方式在约束中引用T,因为它是在类级声明的。

如果您可以编写方法而无法访问集合的私有状态(或者它们是内部的),那么您可以像这样重写:

public class Collection<T>
{
    ...
}

public static class CollectionExtentions
{
    public static bool Equals<T,U>(
            this Collection<T> first, 
            Collection<T> other, 
            EqualityComparer<U> eq) where T : U
    {
            ... // legal to use eq here on the T values with collections
    }
}

顺便提一下,我建议您使用Func<T,T,bool>而不是您自己的命名代理

答案 2 :(得分:0)

如果您明确希望type参数是U的继承类,则不需要泛型,而是使用U作为参数的正式类型。 polimorfism开始了! :)