【问题标题】:Overriding == does't seem to work in inherited class覆盖 == 似乎在继承的类中不起作用
【发布时间】:2017-02-28 22:37:18
【问题描述】:

我正在开发一个程序,它是一个更大程序的一部分,但我创建了这个简单的应用程序来演示我遇到的问题。这是我的代码:

using System;


namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            var bear = new Animal("Bear");
            var bear2 = new Animal("Bear");
            var dog = new Dog("Woof!", "Dog");
            var dog2 = new Dog("Bow-Wow!", "Dog");

            AreEqual(bear, bear2);
            AreEqual(dog2, dog);
        }

        private static void AreEqual(Animal animal1, Animal animal2)
        {
            if (animal1 == animal2)
                Console.WriteLine($"{animal1,15} == {animal2}");
            else
                Console.WriteLine($"{animal1,15} != {animal2}");
        }
    }

    public sealed class Dog : Animal
    {
        public string Action { get; }

        public static bool operator ==(Dog x, Dog y)
        {
            return x.Name == y.Name && x.Action == y.Action;
        }

        public static bool operator !=(Dog x, Dog y)
        {
            return !(x.Name == y.Name && x.Action == y.Action);
        }

        public override bool Equals(object obj)
        {
            if (!base.Equals(obj))
            {
                return false;
            }
            Dog rhs = (Dog)obj;
            return Action == rhs.Action;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode() ^ Action.GetHashCode();
        }

        public Dog(string action, string animalName) : base(animalName)
        {
            Action = action;
        }

        public override string ToString()
        {
            return $"{Name} ({Action})";
        }
    }

    public class Animal
    {
        public string Name { get; }

        public Animal(string animalName)
        {
            Name = animalName;
        }

        public static bool operator ==(Animal x, Animal y)
        {
            return x.Name == y.Name;
        }

        public static bool operator !=(Animal x, Animal y)
        {
            return x.Name != y.Name;
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            if (ReferenceEquals(obj, this))
                return true;
            if (obj.GetType() != GetType())
                return false;

            Animal rhs = obj as Animal;

            return Name == rhs.Name;
        }

        public override int GetHashCode()
        {
            return Name.GetHashCode();
        }

        public override string ToString()
        {
            return Name;
        }
    }
}

当我运行程序时,我在屏幕上看到了这个:

          Bear == Bear
Dog (Bow-wow!) == Dog (Woof!)

这是不正确的。我期待看到的是:

          Bear == Bear
Dog (Bow-wow!) != Dog (Woof!)

在Dog 类中,我覆盖了比较Name 字段和Action 字段的== 运算符。显然 Action 字段对于每个实例都是不同的,所以我不明白为什么说它们是相等的。任何帮助,将不胜感激。我确定这是我忽略的一些简单的事情。

【问题讨论】:

  • 你能在调试会话中单步调试代码吗?
  • 该方法在Animals上运行,而不是Dogs。
  • @pinkfloydx33 - 正确,但不应该像 .ToString() 那样多态性接管并调用正确的方法?
  • 如果您希望相等运算符考虑对象的运行时类型,您可以将方法签名更改为接受dynamic
  • 不,因为相等运算符是静态方法,当然不像您的 ToString 方法那样虚拟。

标签: c# inheritance operator-overloading


【解决方案1】:

您将获得Animal 的== operator,因为AreEqual() 正在对Animals 进行操作。此运算符不是继承的虚方法。如果你想要继承,你应该改用Equals()

【讨论】:

  • 那是我的问题。我假设运算符是虚拟的,并且会在运行时调用正确的运算符重载。
【解决方案2】:

您要重载的运算符是静态的,对于它所属的类来说是静态的。

它具有与new 关键字相似的概念,而不是您希望的override 关键字。

你可以阅读更多关于 new vs override here

基本上,方法的执行取决于您将其转换为的类型。您将两个对象都投射到 Animal 里面

private static void AreEqual(Animal animal1, Animal animal2)

所以 Animal 的 == 运算符被执行。

如果你只是这样做

Console.WriteLine(dog == dog2);

它会返回假。

【讨论】:

  • new 和 override 与运算符重载/静态方法有什么关系?
  • @pinkfloydx33 因为操作符重载是“新”重载而不是“覆盖”重载
  • 好吧,因为没有 static virtual 方法之类的东西,static override 方法当然没有意义。
【解决方案3】:

改变

if (animal1 == animal2)

到

if (animal1.Equals(animal2))

【讨论】:

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