0

我有两个从基类派生的具体类。与具体的 B 类相比,具体的 A 类有十个额外的属性。我有一个方法,其中一个参数是基类列表,如下所示:List<baseClass>. 在方法内部,我必须遍历列表,并转换为适当的具体类并访问属性。请让我知道如何实现这一目标。有什么好的设计模式可以做到这一点吗?

4

5 回答 5

3

c# 有一个GetType方法,您可以查看它。

你也有is运营商

if (baseClass is derivedClass)
{
    // do what you will with derived class.
}

一般来说,你所做的首先是一个糟糕的设计模式。当您遍历基类然后强制转换为派生类时,多态性的全部意义就消失了。

也许您可以在基类中创建一个方法来执行您需要执行的各种操作。

于 2012-09-11T21:53:55.807 回答
2

我猜 C# 的动态类型在这里可以成为你的朋友。

class BaseClass {}

class ConcreteClass1 : BaseClass
{
    void Display1 () {}
}

class ConcreteClass2 : BaseClass
{
    void Display2 () {}
}

void Enumerate (List<BaseClass> baseItems)
{
    foreach (BaseClass baseItem in baseItems)
    {
        ConcreteAccessor ((dynamic)baseItem);
    }
}

void ConcreteAccessor (ConcreteClass1 concreteItem1)
{
    concreteItem1.Display1 ();
}

void ConcreteAccessor (ConcreteClass2 concreteItem2)
{
    concreteItem2.Display2 ();
}    

这里的关键是每个具体类都有不同的重载,并使用dynamic以无缝方式调用其中一个。美妙之处在于,在运行时解决了重载问题,使您的代码看起来很干净。

因为它是运行时类型解析,所以不执行编译时验证。假设您错过了其中一种具体类型的重载,并且运行时将baseItem解析为该特定具体类型。然后它会导致运行时错误 - 崩溃 - 因为没有过载。

另一个问题是动态在引擎盖下使用反射。如您所知,反射会减慢您的应用程序。

于 2012-09-12T09:40:48.453 回答
2

这是基本方法:

foreach(baseClass x in theList)
{
   if (x is classA)
   {
       classA a = (classA) x;
       ...
   }
   else if (x is classB)
   {
       classB b = (classA) x;
       ...    
   }
}

当您需要拆分多种类型时,它并没有变得更简单。您可以尝试使用接口或不同的继承模型来避免整个事情。没有看到更多细节就不可能准确地说出来。

于 2012-09-11T21:54:58.247 回答
1
foreach(var baseClass in baseClasses)
{
    if(baseClass.GetType() == typeof(ClassA)
    {
       var myClassA = (ClassA) baseClass;
        dowork();
    }
    else if(baseClass.GetType() == typeof(ClassB)
    {
       var myClassB = (ClassB) baseClass;
        dowork();
    }

}
于 2012-09-11T21:56:11.107 回答
1

为了避免显式转换,我建议您以不同的方式进行:在您的基类中放置一个抽象方法,该方法将与您的具体类的属性一起使用。

例如:

public abstract void DoSomethingUsingProperties();

在您的具体类中,使用正确的业务逻辑实现(覆盖)它。

然后,在您的方法中,其中一个参数是基类列表,您可以执行以下操作:

public void YourMethod(List<BaseClass> list, ...other params)
{
    // ...

    foreach(var bc in list)
    {
        // so you don't need to know specific properties of concrete classes...
        bc.DoSomethingUsingProperties();
    }

    //...
}
于 2012-09-12T08:50:19.980 回答