【问题标题】:C# Generic Type Parameter Sharing across classesC# 泛型类型参数跨类共享
【发布时间】:2012-02-01 00:52:52
【问题描述】:

假设您有以下通用类层次结构:

public abstract class GenericBase<T>
{
    T SomeProperty{ get; set; }
}

public class Foo<T>
{
    T SomeProperty{ get; set; }
}

public abstract class GenericChild<T> : GenericBase<T>
{
    // ...

    public bool DoSomething(Foo<T> foo)
    {
        // This is invalid:
        return SomeProperty == foo.SomeProperty;
    }
}

DoSomething 方法中的相等性检查无法编译。它会产生以下错误:

Operator '==' cannot be applied to operands of type 'T' and 'T'

如果相关,这些类位于单独的文件中。允许这种平等比较的最佳解决方法是什么?在 C# 中是否有某种模式或某些东西允许这样做?

更新:

一些答案​​建议使用:

where T : SomeClass

不幸的是,T 通常是一个原始类型。

【问题讨论】:

    标签: c# oop generics inheritance


    【解决方案1】:

    == 并非普遍适用于所有类型。它只能在如果 T 被限制为支持它的类型使用,例如where T : class。但是,使用Equals 方法可能会更好地为您服务。

    return SomeProperty.Equals(foo.SomeProperty);
    

    应用了适用的空值检查。

    【讨论】:

    • 这个得到的东西正在编译。但是,如果 DoSomething 是处理器密集型的怎么办?我担心拳击会对性能产生负面影响?
    • 如果类型 T 是一个结构 并且它没有覆盖 Equals,那么装箱将是一个问题。如果 T 提供自己的 Equals 实现,这将不是问题。您只需测量一下这是否是性能问题。您还可以将 T 限制为引用类型。但我愿意相信,如果 DoSomething 是处理器密集型的,那么这些东西(不是装箱)将是你的性能问题。
    【解决方案2】:

    试试这个:

    public abstract class GenericBase<T>
        where T : IEquatable<T>
    {
        public T SomeProperty { get; set; }
    }
    
    public class Foo<T>
    {
        public T SomeProperty { get; set; }
    }
    
    public abstract class GenericChild<T> : GenericBase<T>
        where T : IEquatable<T>
    {
        // ... 
    
        public bool DoSomething(Foo<T> foo)
        {
            // This is valid: 
            return SomeProperty.Equals(foo.SomeProperty);
        }
    }
    

    C# 不知道 == 是否可以应用于 T。

    【讨论】:

    • 实施 IEquatable 的额外好处是什么? 'object.Equals' 方法可以在没有它的情况下工作......
    • 如果您担心性能(正如您在第一个答案的评论中所写),实施 IEquatable 将为您提供强类型解决方案(不会使用装箱或强制转换)
    • 它强制你在为 T 提供的类型中实现 IEquatable。如果你忘记在你的一个类中重写 Object.Equals,那么将使用引用相等!
    【解决方案3】:

    如果你想这样做,你必须提示 T 属于哪种类型。

    例如:

    public abstract class GenericBase<T> where T : MyClass
    {
        T SomeProperty{ get; set; }
    }
    
    public class Foo<T> where T : MyClass
    {
        T SomeProperty{ get; set; }
    }
    
    public abstract class GenericChild<T> : GenericBase<T> where T : MyClass
    {
    }
    

    在你的 MyClass 类中你可以实现 IEquatable 接口,所以你可以做SomeProperty.Equals(foo.SomeProperty)

    如果你不添加 where 约束,你仍然可以使用 object.Equals

    【讨论】:

      【解决方案4】:

      如果要比较 T 类型的对象,可以使用 IEqualityComparer 接口(与给定类型的给定对象进行比较)或强制 T 实现 IEquatable(允许对象与 T 类型的对象进行比较)

      【讨论】:

        猜你喜欢
        • 2016-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多