2

我正在寻找以IEquatable<T>隐式类型检查的方式实现的最佳方法。如果我调用Equals一个子类,我想确保我要比较的类型是相同的。请参阅下面的精简示例。

如果两个Child1对象的 ID 相同,则应将其视为相等。在此示例中,如果它们的 ID 相同,则调用child1.Equals(child2)将返回 true,这不是预期的行为。我基本上想强制实例使用需要参数Child1的重载,而不仅仅是从与.EqualsChild1Child1

我开始认为我以错误的方式处理这个问题。也许我应该把实现留Equals在基类中,并确保this.GetType() == other.GetType()

  public abstract class BaseClass : IEquatable<BaseClass>
  {
    public int ID { get; set; }

    public bool Equals(BaseClass other)
    {
      return 
        other != null &&
        other.ID == this.ID;
    }
  }

  public sealed class Child1 : BaseClass
  {
    string Child1Prop { get; set; }

    public bool Equals(Child1 other)
    {
      return base.Equals(other as BaseClass);
    }
  }

  public sealed class Child2 : BaseClass
  {
    string Child2Prop { get; set; }

    public bool Equals(Child2 other)
    {
      return base.Equals(other as BaseClass);
    }
  }
4

3 回答 3

4

如果您确实需要“强制实例使用需要参数Child1的重载”,则可以使用C# GenericsEqualsChild1

public abstract class BaseClass<T> : IEquatable<T>
    where T : BaseClass<T>
{
    public int ID { get; set; }

    public bool Equals(T other)
    {
        return
            other != null &&
            other.ID == this.ID;
    }
}

public sealed class Child1 : BaseClass<Child1>
{
    string Child1Prop { get; set; }

    public bool Equals(Child1 other)
    {
        return base.Equals(other);
    }
}

public sealed class Child2 : BaseClass<Child2>
{
    string Child2Prop { get; set; }

    public bool Equals(Child2 other)
    {
        return base.Equals(other);
    }
}

这确保您的“Equals”方法只能使用其定义的类型调用。

于 2014-08-22T16:52:32.127 回答
0

你能比较一下每种的类型吗?

  return base.Equals(other as BaseClass) && this.GetType() is other.GetType();

这将比较变量被实例化的实际类型。我创建了一个 .net 小提琴,位于此处:https ://dotnetfiddle.net/rOeuuo

这是代码(在vb中)

Imports System

Public Module Module1
    Public Sub Main()
        dim x as testparent = new testchild1
        dim y as testparent = new testchild2

        if x.GetType() is y.Gettype() then
            console.writeline("they are the same type")
        else
            console.writeline("they are different types")
        end if


    End Sub


End Module

public class testparent
    end class


    public class testchild1: inherits testparent

    end class


public class testchild2: inherits testchild1

    end class

这是另一个小提琴,其中两个子类直接从基类继承,而不是从彼此继承(我认为这是你最初的问题):https ://dotnetfiddle.net/ViNqej

Imports System

Public Module Module1
    Public Sub Main()
        dim x as testparent = new testchild1
        dim y as testparent = new testchild2

        if x.GetType() is y.Gettype() then
            console.writeline("they are the same type")
        else
            console.writeline("they are different types")
        end if


    End Sub


End Module

public class testparent
    end class


    public class testchild1: inherits testparent

    end class


public class testchild2: inherits testparent

    end class
于 2014-08-22T16:41:42.813 回答
0

您在这里有几个选择:

  1. 您可以在此处检查每个方法中的实际运行时类型,Equals并验证它不是您自己建议的子类型。这实际上是一个合理的解决方案。

  2. 您可以使每个Equals方法都是虚拟的。让每个派生类型覆盖其父类的Equals方法,或者静态return false地或者尝试强制转换为“你的”类型,return false如果你不能。

  3. 使用==运算符而不是Equals. 它的定义可能想要也可能不想检查操作数的运行时类型并验证它们不是子类型。

这里的一个关键行为是您不必试图阻止您类型的用户将您的对象与另一种类型的对象进行比较。除了崩溃之外,您实际上还有一个明智的行为。你可以return false。您可以比较老虎和大象。它们是不同的,但你当然可以比较它们。

于 2014-08-22T16:47:01.010 回答