C# 访问抽象类列表中的信息

C# 访问抽象类列表中的信息,c#,list,inheritance,abstract-class,C#,List,Inheritance,Abstract Class,我有下面显示的代码。我创建了一个动物列表(“list),其中添加了几只猫、狗和鸟。是否可以通过该列表直接访问每个类的不同字段,如狗的年龄或猫的颜色 谢谢大家! public abstract class Animals { } public class Cat : Animals { public string Name; public string Color; public int Age; public string Breed } public

我有下面显示的代码。我创建了一个动物列表(“list),其中添加了几只猫、狗和鸟。是否可以通过该列表直接访问每个类的不同字段,如狗的年龄或猫的颜色

谢谢大家!

public abstract class Animals
{
}


public class Cat : Animals
{
    public string Name;
    public string Color;
    public int Age;
    public string Breed  
}


public class Dog : Animals
{
    public string Name;
    public string Color;
    public int Age;
    public string Breed
}

public class Bird : Animals
{
    public string Name;
    public int Age;
    public string Wing_Color;
    public string Fly_Height;
}
是否可以通过该列表直接访问每个类的不同字段,如狗的年龄或猫的颜色

是的,但前提是您在编译时知道类型

C#还不支持正确的代数类型或有区别的并集,因此要进行彻底的检查,您需要使用
is
运算符(理想情况下使用)或定义自己的
匹配方法

像这样:

abstract class Animal
{
    public TResult Match<TResult>(
        Func<Cat ,TResult> isCat,
        Func<Dog ,TResult> isDog,
        Func<Bird,TResult> isBird
    )
    {
        if     ( this is Cat  c ) return isCat( c );
        else if( this is Dog  d ) return isDog( d );
        else if( this is Bird b ) return isBird( b );
        else                      throw new InvalidOperationException( "Unknown animal subclass." );
    }
}
方法1:使用
is
操作员:
is
操作符的这种使用有时被称为“模式匹配”——但我不同意这个说法,因为它实际上只是对运行时类型检查语法的一种工效学改进,而不是对数据进行真正的(在Haskell意义上)模式匹配

List<Animal> animals = ...

foreach( Animal a in animals )
{
    if( a is Cat cat )
    {
        Console.WriteLine( "Cat breed: {0}.", cat.Breed );
    }
    else if( a is Dog dog )
    {
        Console.WriteLine( "Dog breed: {0}.", dog.Breed );
    }
    else if( a is Bird bird )
    {
        Console.WriteLine( "Bird name: {0}.", bird.Name );
    }
    else
    {
        throw new InvalidOperationException( "Unknown animal subclass." );
    }
}
这样使用:

foreach( Animal a in animals )
{
    String summary = a.Match(
        isCat : c => "Cat breed: " + c.Breed,
        isDog : d => "Dog breed: " + d.Breed,
        isBird: b => "Bird name: " + b.Name,
    );

    Console.WriteLine( summary );
}

由于所有动物都有名称和年龄,我建议使用更好的设计,将这些字段移动到抽象父类,并为它们定义抽象getter:

public abstract class Animal
{
    public string Name;
    public int Age;
    abstract string getName();
    abstract int getAge();
}


public class Cat : Animal
{
    public string Breed  
}


public class Dog : Animal
{
    public string Color;
    public string Breed
}

public class Bird : Animal
{
    public string Wing_Color;
    public string Fly_Height;
}

您应该在Animals类中放置公共属性。使用编程语言
公共抽象类Animals
的标记问题不应该有复数名称。它应该是
公共抽象类Animal