运行时确定对象类型

时间:2015-05-07 10:50:04

标签: c# inheritance abstract-class

我在C#中编程。我有一个抽象类(Animal)和两个从Animal继承的派生类(Dog和Cat)。我还有一个名为" Value"的静态方法。适用于Dog和Cat。但是,我的用户可能会调用此方法传递Animal。

如何确定它是狗还是猫? 我可以"标记"以某种方式上课? 如果我的设计错了,请告诉我,如果我做的是我不应该做的事情。

以下是一些示例代码。下面的最后一个函数(Value(Animal animal))是我不确定的函数。

public abstract class Animal
{
    public Animal(string name)
    {
        Name = name;
    }

    public readonly string Name;
}

public class Dog : Animal
{
    public Dog(string name, double weight)
        : base(name)
    {
        Weight = weight;
    }

    public readonly double Weight;
}

public class Cat : Animal
{
    public Cat(string name, bool old)
        : base(name)
    {
        Old = old;
    }

    public readonly bool Old;
}

public class AnimalValuation
{
    public static double Value(Dog dog)
    {
        return dog.Weight;
    }

    public static double Value(Cat cat)
    {
        if (cat.Old == true)
        {
            return 100.0;
        }
        else
        {
            return 0.0;
        }
    }

    public static double Value(Animal animal)
    {
        // if animal is Dog then do something like:
            Dog dog = (Dog)animal;
            return Value(dog);
        // if animal is Cat then do something like:
            Cat cat = (Cat)animal;
            return Value(cat);
    }
}

4 个答案:

答案 0 :(得分:2)

该运算符实际上是is

public static double Value(Animal animal)
{
    if (animal is Dog) {
        Dog dog = (Dog)animal;
        return Value(dog);
    }
    if (animal is Cat) {
        Cat cat = (Cat)animal;
        return Value(cat);
    }
}

另一种方法是使用抽象(虚拟)方法将值计算放在每个实现中:

public abstract class Animal {

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

    public readonly string Name;

    public abstract double Value();

}

public class Dog : Animal {

    public Dog(string name, double weight) : base(name) {
        Weight = weight;
    }

    public readonly double Weight;

    public override double Value() {
        return dog.Weight;
    }

}

public class Cat : Animal
{
    public Cat(string name, bool old) : base(name) {
        Old = old;
    }

    public readonly bool Old;

    public override double Value() {
        if (Old) {
            return 100.0;
        } else {
            return 0.0;
        }
    }

}

然后你不需要估价助手类,你可以使用:

double value = someAnimal.Value();

这种方法会强制您为您创建的任何新动物类实施Value方法,因此您不必冒险忘记将其放入估价助手中。此外,任何人都可以在不需要更改估价助手的情况下实施新动物。

答案 1 :(得分:1)

你的方法是正确的,但我相信你应该在这里使用多态而不是静态Value方法重载。

那么......为什么你不在Value中声明一个抽象的Animal属性,然后你就可以独立于Value的实际具体类型访问Animal(即DogCat)?

public abstract class Animal
{
    public Animal(string name)
    {
        Name = name;
    }

    public readonly string Name;

    public abstract double Value { get; }
}

public class Dog : Animal
{
    public Dog(string name, double weight)
        : base(name)
    {
        Weight = weight;
    }

    public readonly double Weight;

    public override double Value { get { return Weight; } }
}

public class Cat : Animal
{
    public Cat(string name, bool old)
        : base(name)
    {
        Old = old;
    }

    public readonly bool Old;

    public override double Value { get { return Old ? 0 : 100; } }
}

现在它很容易。如果将Animal派生的类对象引用作为其派生类进行输入,则可以访问Value,并且您将获得没有静态的正确值和期望值:

Dog dog = new Dog("Bobby", 30);
Cat cat = new Cat("Kitty", false);

// We upcast Dog and Cat to Animal, but Value implementation
// is defined by the derived class, so even if you access
// Value from an Animal-typed reference, the Value will be
// the expected one for cats and dogs :)
Animal a1 = dog;
Animal a2 = cat;

double a1Value = a1.Value;
double A2Value = a2.Value;

注意

正如@DarrenYoung在一些评论中所说,魔术数字是一个坏主意。由于Dog.Value是权重而Cat.Value是谁知道什么(0或100 ...),这可能导致混淆,使用类型为Animal的引用的代码将无法知道Animal.Value指的是什么......

顺便说一下,我只是想提供一种软件架构方法,而且由于OP缺乏更多信息,我觉得我们无法深入了解Value的实际含义。

答案 2 :(得分:0)

您编写的代码是(或至少'a')确定给定对象的派生类型最多的正确方法。

然而,我建议您的代码设计可能会引起一些注意。我不知道'Value'方法在您的生产应用程序中扮演什么角色,但我认为它应该是Animal类型的成员,并被Dog覆盖,Cat等...

答案 3 :(得分:0)

if(animal.GetType() == typeof(Dog))

if(animal is Dog)