2016-06-23 36 views
0

我有几个派生类都来自同一个基类。从基类集合中检查派生类的类型

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 
} 

我已经看过几种方法来处理这个问题。起初我曾尝试过抓住方块,然后试图将抓到的无效物体施放,然后再次施放。这似乎很混乱,所以我试图做一个检查。

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; 
    } 
} 

通过所有这些步骤会后,我想知道处理这类问题的正确方法是什么,因为这一切似乎更令人费解比它也许应该。

由于

+0

_“执行特定的操作取决于派生类类型” _ - 那么你使用继承错误。请尝试非常明确地解释(而不是使用名为base,one,two和three的人为示例,但使用您的实际代码)为什么您认为您需要这样做。总的来说,事实证明你完全不需要这个,并且对它的需求将会消失。 – CodeCaster

+1

在每个这些类中添加一个overide方法,并使该方法执行不同的任务。所以这将是entry.method() – Dheeraj

+0

你试过如果(entry.GetType()== typeof(ClassOne))'或'如果(条目是ClassOne)'? –

回答

3

执行取决于类型不同的操作正确的方法是通过使用抽象方法。

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);

foreach (Base entry in objects) 
{ 
    switch (entry.GetType().Name) 
    { 
     case (nameof(ClassOne)): 
      // Do something 
      break; 
     case (nameof(ClassTwo)): 
      // Do something else 
      break; 
    } 
} 
+0

用错误的回复发表了这篇文章:对不起,这是错综复杂的。用哺乳动物的例子说明了我被教导继承的方式(我不知道这有多普遍)。但它基本上是以哺乳动物为基础的,它有走路,吃东西,喝东西,睡觉等等东西。然后你有像Fox:Mammal {}这样的东西,并添加像传真机那样(在我的例子中)的洞穴()马:哺乳动物{}不。这是否意味着哺乳动物具有每种哺乳动物可能使用的一切抽象方法? – StewVanB

0

这应该工作:

Base[] collection; 

foreach(var item in collection){ 
    if((item as TypeYouWhant) == item){ 
     ... 
    } 
} 
+0

你应该总是添加一些解释到你的答案,以提高他们的质量。 – m02ph3u5

0

@Massimiliano吉拉迪是指出了您准时问题corrent。只需在原始循环中用var替换Base即可提取所需的类型信息。你可以避免去掉枚举的兔子洞。

你说得很对,指出具有重写方法的类型层次结构并不是每个问题的答案。

你可能会考虑一个更具可读性,可测试性的功能性方法,我认为它比switch函数或一系列if函数中的函数方法更具可维护性。我离开你用此溶液(您可以用它在这里玩:https://repl.it/C59q/3):

using System; 
using System.Collections.Generic; 

class Base {} 
class ClassOne : Base { 
    public void doOne(){ 
     Console.WriteLine("doing one") ; 
    } 
} 

class ClassTwo : Base { 
    public void doTwo(){ 
     Console.WriteLine("doing two"); 
    } 

} 
class ClassThree : Base { 
    public void doThree(){ 
      Console.WriteLine("doing three"); 
     } 
} 


class MainClass { 

    static Base[] objects = { 
    new ClassOne(), 
    new ClassTwo(), 
    new ClassThree() 

    };  

    public static void Main (string[] args) { 

    Action<ClassOne> ClassOneFunc = delegate(ClassOne o) 
     {o.doOne();}; 
    Action<ClassTwo> ClassTwoFunc = delegate(ClassTwo o) 
     { o.doTwo();}; 
    Action<ClassThree> ClassThreeFunc = delegate(ClassThree o) 
     { o.doThree();}; 

    var contents = new Dictionary<System.Type, Action<dynamic>> 
     { 
      {typeof(ClassOne), ClassOneFunc}, 
      {typeof(ClassTwo), ClassTwoFunc}, 
      {typeof(ClassThree), ClassThreeFunc}, 

     }; 

    Action<dynamic> worker = o => contents[o.GetType()](o); 





    foreach(var each in objects){ 
    worker(each); 

    } 
}} 
+0

感谢您的回答罗伯特,这似乎是我应该知道如何在我的正常C#工作中做的事情。这个用法叫做什么?我想知道我应该在哪里了解更多关于你在这里做什么的信息。然而,我不认为这对我正在努力完成的工作有效。 – StewVanB

+0

我会用c#调用它,而不是使用OO风格。 –