C# 从基类集合中检查派生类的类型
我有两个派生类,它们都来自同一个基类C# 从基类集合中检查派生类的类型,c#,inheritance,collections,derived-class,base-class,C#,Inheritance,Collections,Derived Class,Base Class,我有两个派生类,它们都来自同一个基类 class Base {} class ClassOne : Base {} class ClassTwo : Base {} class ClassThree : Base {} 假设我有一个由这些类对象组成的数组,我需要遍历该数组并根据派生类类型执行特定操作 Base[] objects; foreach(Base entry in objects){ //Check for class type to perform operations
class Base {}
class ClassOne : Base {}
class ClassTwo : Base {}
class ClassThree : Base {}
假设我有一个由这些类对象组成的数组,我需要遍历该数组并根据派生类类型执行特定操作
Base[] objects;
foreach(Base entry in objects){
//Check for class type to perform operations
}
我已经研究了几种处理方法。起初,我确实尝试了catch块,然后尝试转换捕获到无效转换的对象,然后尝试了另一个转换。这看起来很混乱,所以我试着做一个if检查
if(entry.GetType() == ClassOne){}
else if(entry.GetType() == ClassTwo){}
但这不起作用,因为它们都被认为是代码中该实例的基类型
我现在所做的是添加一个包含所有派生类类型的枚举,并在创建对象时在构造函数中设置它
public enum DerivedClassType{
Base,
One,
Two,
Three
}
现在,我的foreach有一个开关,可以在尝试强制转换之前检查该类型
Base[] objects;
foreach(Base entry in objects){
switch(entry.derivedClassType){
case DerivedClassType.One:
((One)entry).DoOneStuff();
break;
case DerivedClassType.Two:
break;
case DerivedClassType.Three:
break;
}
}
在经历了所有这些步骤之后,我想知道处理这类问题的正确方法是什么,因为这一切似乎比它可能应该的复杂得多
感谢根据类类型执行不同操作的正确方法是使用抽象方法
abstract class Base
{
public abstract void DoSomethingWithArg(string arg);
}
class ClassOne : Base
{
public override void DoSomethingWithArg(string arg)
{
Console.WriteLine($"Class One says {arg}");
}
}
class ClassTwo : Base
{
public override void DoSomethingWithArg(string arg)
{
Console.WriteLine($"Class Two says {arg}");
}
}
然后像这样使用它
Base[] objects;
foreach (Base entry in objects)
{
entry.DoSomethingWithArg("Hello");
}
如果您真的想继续执行可能无法维护的代码,可以这样实现(需要C#6)
根据类类型执行不同操作的正确方法是使用抽象方法
abstract class Base
{
public abstract void DoSomethingWithArg(string arg);
}
class ClassOne : Base
{
public override void DoSomethingWithArg(string arg)
{
Console.WriteLine($"Class One says {arg}");
}
}
class ClassTwo : Base
{
public override void DoSomethingWithArg(string arg)
{
Console.WriteLine($"Class Two says {arg}");
}
}
然后像这样使用它
Base[] objects;
foreach (Base entry in objects)
{
entry.DoSomethingWithArg("Hello");
}
如果您真的想继续执行可能无法维护的代码,可以这样实现(需要C#6)
这应该起作用:
Base[] collection;
foreach(var item in collection){
if((item as TypeYouWhant) == item){
...
}
}
这应该起作用:
Base[] collection;
foreach(var item in collection){
if((item as TypeYouWhant) == item){
...
}
}
@马西米利亚诺·吉拉迪正确地指出了你的守时问题。只需在原始循环中用var替换Base,就可以提取所需的类型信息。你本可以避免进入枚举的兔子洞 您正确地指出,具有重写方法的类型层次结构并不是所有问题的答案
您可能会考虑一种更具可读性、可测试性的功能性方法,并且我认为它比在开关状态或IFS系列中调用函数方法更具可维护性。我留给你这个解决方案(你可以在这里玩:):
使用系统;
使用System.Collections.Generic;
类基{}
第一类:基本类{
公共空间{
Console.WriteLine(“做一件”);
}
}
第二类:基本类{
公开无效doTwo(){
Console.WriteLine(“做两件事”);
}
}
第三类:基础{
公共无效的doThree(){
控制台。写线(“做三个”);
}
}
类主类{
静态基[]对象={
新类一(),
新类二(),
新类别三()
};
公共静态void Main(字符串[]args){
动作ClassOneFunc=委托(一级o)
{o.doOne();};
动作ClassTwoFunc=委托(Class2 o)
{o.doTwo();};
动作ClassThreeFunc=委托(ClassThree o)
{o.doThree();};
var contents=新字典
{
{typeof(ClassOne),ClassOneFunc},
{typeof(ClassTwo),ClassTwoFunc},
{typeof(ClassThree),ClassThreeFunc},
};
Action worker=o=>contents[o.GetType()](o);
foreach(对象中的每个变量){
工人(每人);
}
}}
@Massimiliano Girrdi正确地指出了你的守时问题。只需在原始循环中用var替换Base,就可以提取所需的类型信息。你本可以避免进入枚举的兔子洞
您正确地指出,具有重写方法的类型层次结构并不是所有问题的答案
您可能会考虑一种更具可读性、可测试性的功能性方法,并且我认为它比在开关状态或IFS系列中调用函数方法更具可维护性。我留给你这个解决方案(你可以在这里玩:):
使用系统;
使用System.Collections.Generic;
类基{}
第一类:基本类{
公共空间{
Console.WriteLine(“做一件”);
}
}
第二类:基本类{
公开无效doTwo(){
Console.WriteLine(“做两件事”);
}
}
第三类:基础{
公共无效的doThree(){
控制台。写线(“做三个”);
}
}
类主类{
静态基[]对象={
新类一(),
新类二(),
新类别三()
};
公共静态void Main(字符串[]args){
动作ClassOneFunc=委托(一级o)
{o.doOne();};
动作ClassTwoFunc=委托(Class2 o)
{o.doTwo();};
动作ClassThreeFunc=委托(ClassThree o)
{o.doThree();};
var contents=新字典
{
{typeof(ClassOne),ClassOneFunc},
{typeof(ClassTwo),ClassTwoFunc},
{typeof(ClassThree),ClassThreeFunc},
};
Action worker=o=>contents[o.GetType()](o);
foreach(对象中的每个变量){
工人(每人);
}
}}
“根据派生类类型执行特定操作”-那么您使用的继承是错误的。请尝试非常明确地解释(不要使用名为base、one、two和three的人为示例,而是使用您的实际代码)为什么您认为需要这个。通常情况下,您根本不需要它,对它的需求也会消失。在每个类中添加一个overide方法,并使该方法执行不同的任务。那就是entry.method(),你有没有试过if(entry.GetType()==typeof(ClassOne))
或者if(entry是ClassOne)
?好吧,我试着让这个例子简单到只问我想要回答的问题。让我看看是否可以更明确一些。我有一个名为ObjectiveBase的基类,它具有我所有目标共享的功能。但我有不同类型的目标,比如ObjectiveZone、ObjectivePath、ObjectiveWatch。我的代码收集所有目标并存储