c#铸造想法解释

时间:2018-04-17 09:46:55

标签: c# inheritance casting

我正在网上学习C#,我面对这个无法理解的事情, 考虑这个动物类

public class Animal
{
    public int Age { set; get; }
    public string Name { set; get; }
    public double Weight { set; get; }

    public Animal()
    { }

    public Animal(int Age, string Name, double Weight)
    {
        this.Age = Age;
        this.Name = Name;
        this.Weight = Weight;
    } 
}

继承自Animal的狗类

class Dog : Animal
{
    public string color { set; get; }

    public Dog()
    {
    }

    public Dog(int Age, string Name, double Weight, string color) : base(Age, Name, Weight)
    {
        this.color = color;
    }
    public string EmptyMethod()
    {
        return(" i am dog method ");
    }
}

在程序类的Main方法

        static void Main(string[] args)
    {
        List<Animal> MyAnimals = new List<Animal>();
        List<Dog> MyDogs = new List<Dog>();

        MyAnimals.Add(new Animal());
        MyAnimals.Add(new Dog());

        foreach (var item in MyAnimals)
        {
            Console.WriteLine(item.GetType().Name);
            if (item is Dog)
            {
                Console.WriteLine(item.GetType().Name + " i am dog between Animal");
              //Here i got a compiling error and can't reach the dog empty method even after checking it's a Dog object !!! Why
             var tryingToReachDogMethod = item.EmptyMethod();

            }
        }

        Animal smallAnimal = new Animal();
        MyDogs.Add(new Dog());
        MyDogs.Add(smallAnimal as Dog);

        foreach (var item in MyDogs)
        {
            //Here i Can reach the Empty Method from Dog Class !!!
            //i know it will give runtime error because some objects is not 
            //dogs and don't have it's method to implement it 
            var tryingToReachDogMethod = item.EmptyMethod();

            if (item is Animal)
            {
                Console.WriteLine("i am animal as dog");
            }
        }

我在第三段代码中评论我的问题,(代码是我几天前写的练习之一),那么为什么程序员会制作动物列表然后在其中放入一个更发达的对象(在来自类dog的示例对象)以及为什么任何人会做相反的事情?为什么要从开发的对象(在示例狗中)制作一个列表,然后尝试将Less开发类型的对象放入其中, 你能从真正的编程解决方案中举例说明吗?

3 个答案:

答案 0 :(得分:3)

MyDogs是一个狗列表。您只能向其添加Dog

问题出在这一行:

MyDogs.Add(smallAnimal as Dog);
你可能认为你把这只动物卖给了一只狗。事实并非如此。你试图施展它,但它失败了。由于您使用as,因此不会抛出异常,而是返回null。现在,您的列表中有null Dog。当您尝试访问该实例的成员时,将获得空引用异常。

答案 1 :(得分:0)

原因item仍为Animal,因为您有List<Animal> MyAnimals = new List<Animal>();Animal类型没有EmptyMethod()。因此,您需要将其明确地转换为Dog类型,如下所示,以便调用所需的方法

var tryingToReachDogMethod = ((Dog)item).EmptyMethod()

(或者)你也可以使用as运算符和空传播运算符(如

Dog d = item as Dog;
var tryingToReachDogMethod = d?.EmptyMethod();

答案 2 :(得分:0)

使用基类或接口定义的列表中的“更开发”对象的“更开发”版本的真实世界示例是“命令”模式。

给定这样的界面:

public interface ICommand 
{
    void Execute();
}

您可能希望逐个执行许多不同的ICommand实现。你会把它们全部放在某种List

var commands = new List<ICommand>();
commands.Add(new Command1());
commands.Add(new Command2());

全部执行。你不需要知道它是什么类型的命令,只是它们都有一个Execute方法

foreach(var command in commands)
     command.Execute();

这表明了Polymorphism