【问题标题】:How can a static method invoke a virtual method?静态方法如何调用虚拟方法?
【发布时间】:2018-03-27 00:58:47
【问题描述】:

在为自定义对象编写自己的相等逻辑时,可以做一些事情。其中两种做法包括重载== 运算符和覆盖obj.Equals() 方法。 下面,我们只对父类Animal 和子类Hominoidea 执行此操作。

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

   public override bool Equals(object obj)
   { ... }

   ...
}

public class Hominoidea : Animal
{
   public static bool operator ==(Hominoidea x, Hominoidea y)
   {
      return object.Equals(x, y);
   }

   public override bool Equals(object obj)
   { ... }

   ...
}

如果我们能够轻松地比较某种动物而不管它们的派生类(人科、猫科等),我们会利用基类的简单逻辑,可能会写一些类似的东西:

static void DisplayWhetherEqual(Animal animal1, Animal animal2)
{
   if (animal1 == animal2)
   {
      Console.WriteLine(string.Format("{0,12} == {1}", animal1, animal2));
   }
   else
      Console.WriteLine(string.Format("{0,12} != {1}", animal1, animal2));
}

如果我们传入Hominoidea对象,代码将首先为Animal类执行static重载==,然后为子类Hominoidea类执行虚拟object.Equals(x, y)

当将这两个Hominoidea 类与Animals 进行比较时,编译器如何在static 运算符方法中调用正确的虚拟object.Equals() 方法?我认为@ 中的所有内容987654339@ 方法也必须是static

【问题讨论】:

  • 想象一下,如果你叫x.Equals(y)而不是object.Equals(x, y)
  • 您的两个== 重载都调用相同的static 方法。
  • 查看object.Equals的实现
  • 您可能还想阅读this question. 的答案(尤其是 Eric Lippert 的答案)

标签: c# .net static overriding overloading


【解决方案1】:

静态方法当然可以访问实例方法;没有它们,您将无法做任何非常有趣的事情。静态类缺少的是它自己的实例(关键字this 在静态方法内部未定义)。但是您可以在传递给它或以其他方式提供的任何对象上调用实例方法。

所以虽然你不能这样做

class MyClass
{
    static void Print()
    {
        Console.WriteLine(this.ToString());  //Does not compile
    }
}

你肯定能做到这一点

class MyClass
{
    static void Print(MyClass instance)
    {
        Console.WriteLine(instance.ToString());  //Compiles, because it references an object that was passed in
    }
}

还有这个

class MyClass
{
    static private MyClass _anInstance = new MyClass();

    static void Print()
    {
        Console.WriteLine(_anInstance.ToString());  //Compiles, because it references an object instance held in a static variable
    }
}

【讨论】:

    【解决方案2】:

    我认为静态方法中的所有内容也必须是静态的

    是什么让你这么认为?没有这样的规则。静态方法不附加到类的特定实例(这就是为什么它们在 VB 中称它们为Shared,这意味着它们在所有实例之间共享),但在其他方面它们与实例方法没有什么不同。

    考虑一下

    public class Person {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    
        public static string GetInitials(Person person) {
            return person.FirstName[0].ToString() + person.LastName[0].ToString();
        }
    }
    

    static 方法GetInitials() 可以访问传递给它的实例的属性。所以你可以写这段代码:

    var p = new Person();
    p.FirstName = "Joe";
    p.LastName = "Smith";
    Console.WriteLine(Person.GetInitials(p));
    

    【讨论】:

    • “我认为静态方法中的所有内容也必须是静态的” 是什么让我认为这是对编译时发生的事情的误解,实际上是夸大其词。我想因为该方法无法实例化,那么它怎么能动态调用其他东西的虚拟。我只是粗暴地扩展了思路并做出了错误的假设。谢谢你的回答。
    猜你喜欢
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 2017-10-08
    • 2016-09-13
    • 1970-01-01
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多