c# - 访问抽象类列表中的信息
问题描述
我有下面显示的代码。我创建了一个动物列表(“List< Animals >”),在其中添加了几个 Cat、Dog 和 Bird。是否可以直接访问每个类的不同字段,例如狗的年龄或猫的颜色列表?
谢谢!
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
运算符(最好使用ExhaustiveMatching 之类的代码分析包)或定义自己的Match
方法。
像这样:
方法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." );
}
}
如果您定义了要切换的封闭类型层次结构(如 Java 样式的枚举类)(使用带有-syntax 的C# 7.x语句)但不存在,则ExhaustiveMatching之类的代码分析包会给您编译时警告或错误子类案例。switch
case TypeName name:
方法 2:使用自定义匹配/切换方法:
定义自定义Match
或Switch
方法允许您要求使用调用站点是详尽无遗的,但这取决于您的Match
/Switch
方法是否详尽 - 但由于它将责任负担转移给您 - 而不是消费者 - 这种方法具有优势.
像这样:
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." );
}
}
像这样使用:
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 );
}
推荐阅读
- chef-infra - 如何在测试厨房的节点上启用特定的 Ohai 插件
- mysql - 检查日期可用性的子查询
- c++ - 使用 Conan 直接从 GitHub 安装包
- omnet++ - 如何将 'const omnetpp::SimTime' 转换为 'double'
- dialogflow-es - 在荷兰测试 Actions on Google Transaction API 时出现“抱歉,我无法在您所在地区收款”消息
- aurelia - 在转发器中使用 @computedFrom 数组
- r - 具有灵活函数参数的复杂 if else 函数的代码改进
- c# - .NET Framework 依赖树
- aframe - 有没有办法在 3d 模型中的特定网格上执行动画
- apache-kafka - Kafka:手动分配的消费者由于“GroupAuthorizationException”而无法提交或关闭