为何遍历MyAnimals无法获取所有成员?如何无需OfType遍历全部对象?
问题解答
1)为何首次遍历无法获取所有成员?
咱们先拆解这段代码的核心逻辑:(x as Animal) 是在尝试把集合里的对象强制转换为Animal类型,但as运算符有个特点——如果转换失败(也就是当前对象根本不是Animal的子类/实现类实例),就会返回null,而你打印的是Type属性,null值自然不会输出有效内容。
你提到用MyAnimals.OfType<Zebra>()能拿到Zebra对象,这说明你的MyAnimals集合里的Zebra对象并没有继承Animal类,但Cat、Dog是明确继承了Animal的。所以当你用as Animal转换Zebra时必然失败,返回null,也就看不到它的输出;而Cat、Dog能成功转换,所以能正常打印出Type。
举个贴合你场景的代码例子:
public class Animal { public string Type { get; set; } } public class Cat : Animal { } public class Dog : Animal { } public class Zebra { } // 注意:这个类没继承Animal // 集合里的元素示例 var MyAnimals = new List<object> { new Cat{Type="Cat"}, new Dog{Type="Dog"}, new Zebra() };
这时候用x as Animal转Zebra就会得到null,自然打不出有效内容。
2)如何无需手动为每种类型使用OfType()来遍历所有对象?
想要遍历所有对象并获取类型相关信息,完全不用逐个写OfType<T>,这里给你几个实用方案:
方案一:直接获取对象的运行时类型名称
如果只是想输出每个对象的类型标识,不需要依赖Animal的Type属性,直接用GetType()获取对象的实际运行时类型即可:
foreach (var x in MyAnimals) { Print(x.GetType().Name); // 会输出Cat、Dog、Zebra,每个对象的真实类型名 }
方案二:定义共同接口(推荐,更规范)
如果你的所有“动物”类型都应该具备Type属性,最规范的做法是定义一个通用接口,让所有类型都实现它:
public interface IAnimal { string Type { get; } } public class Animal : IAnimal { public string Type { get; set; } } public class Cat : Animal { } public class Dog : Animal { } public class Zebra : IAnimal { public string Type => "Zebra"; } // 实现接口
之后遍历的时候直接转换为IAnimal,所有实现了接口的对象都能成功转换并输出Type:
foreach (var x in MyAnimals) { var animal = x as IAnimal; if (animal != null) { Print(animal.Type); } }
方案三:反射获取Type属性(万不得已才用)
如果没办法修改现有类的定义,也可以用反射来读取Type属性,但这种方式性能较差,不推荐在高频场景使用:
foreach (var x in MyAnimals) { var typeProp = x.GetType().GetProperty("Type"); if (typeProp != null) { var typeValue = typeProp.GetValue(x)?.ToString(); Print(typeValue); } }
内容的提问来源于stack exchange,提问作者T.Todua
相关产品推荐
相关产品推荐

