为什么编译器无法解析方法覆盖?

时间:2016-04-27 12:46:24

标签: c# polymorphism

在以下C#代码段

public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal sound");
    }
}

public class Dog:Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Dog sound");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Animal an = new Dog();
        an.MakeSound();           
        Console.ReadLine();
    }
}

要调用的方法是在运行时确定的。为什么编译器确切无法弄清楚,调用哪种方法?

为什么编译器不会看到an引用Dog对象然后从该类中选择方法?

运行时如何确定调用哪个方法?

4 个答案:

答案 0 :(得分:3)

这听起来很像考试/家庭作业问题。但是,让我用另一个问题回答你的问题。 请考虑以下代码:

static void Main(string[] args)
{
    var random = new Random();
    Animal an = null;
    if (random.NextDouble() < 0.5) {
      an = new Dog();
    } else {
      an = new Cat();
    }

    an.MakeSound();           
    Console.ReadLine();
}

编译器如何知道在编译时调用哪种方法?它不能,仅在运行时是已知的具体类型。

答案 1 :(得分:0)

你告诉compilier这个变量属于Animal类型。它只查看声明,而您希望它执行您的代码以弄清楚您的意思。这不是它的工作原理。

答案 2 :(得分:0)

请考虑以下代码:

class Program
{
    static void Main(string[] args)
    {
        Animal dog = new Dog();
        MakeSoundAbstract(dog);

        Animal an = new Animal();
        MakeSoundAbstract(an);

        Console.ReadLine();
    }

    static void MakeSoundAbstract(Animal animal)
    {
        animal.MakeSound();
    }
}

如果编译器将在编译期间确定虚拟调用而不是在运行时期间,那么MakeSoundAbstract方法将始终执行MakeSound class Animal方法,因此我们将失去https://technet.microsoft.com/en-us/library/ms173248%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396的强大功能。

答案 3 :(得分:0)

考虑对您的代码进行此更改:

public class Animal
{
  public virtual void MakeSound()
  {
    Console.WriteLine("Animal sound");
  }
}

public class Dog : Animal
{
  public override void MakeSound()
  {
    Console.WriteLine("Woof!");
  }
}

public class Cat : Animal
{
  public override void MakeSound()
  {
    Console.WriteLine("Purrrrrrrrrrrrrr");
  }
}

class Program
{
  static void Main(string[] args)
  {
     Animal an = GetAnimal(DateTime.Now);
     an.MakeSound();           
     Console.ReadLine();
  }

  private Animal GetAnimal(DateTime dateTime)
  {
    if (dateTime.DayOfWeek == DayOfWeek.Monday)
    {
      return new Dog();
    }
    else
    {
      return new Cat();
    }
  }
}

现在无法知道在编译时要创建什么类型的动物,因为它取决于代码实际运行的星期几。星期一你会得到一只狗,但在任何时候你都会得到一只猫。这是多态的一个定义好处 - 类型不是由编译器烘焙的,而是在代码执行时动态派生的。多态性允许您使用这些派生类型,即使您在编写代码时并不确切知道它们是什么(但您确实知道它们是所有类型的动物)。