我有两个从基类派生的具体类。与具体的classB相比,具体的classA有十个额外的属性。我有一个方法,其中一个参数是基类列表,如下所示:List<baseClass>
。在方法内部,我必须遍历列表,并转换为适当的具体类并访问属性。请让我知道如何实现这一目标。有没有好的设计模式呢?
答案 0 :(得分:3)
c#有一个GetType方法,您可以查看。
您还拥有is
运算符
if (baseClass is derivedClass)
{
// do what you will with derived class.
}
但是
一般来说,你所做的是一个糟糕的设计模式。当您遍历基类然后转换为派生类时,多态性的整个点就会丢失。
也许您可以在基类中创建一个可以执行您需要执行的操作的方法。
答案 1 :(得分:2)
这是基本方法:
foreach(baseClass x in theList)
{
if (x is classA)
{
classA a = (classA) x;
...
}
else if (x is classB)
{
classB b = (classA) x;
...
}
}
当您需要拆分多个类型时,它并不简单。您可以尝试使用接口或不同的继承模型来避免整个事情。 没有看到更多细节就不可能完全说出来。
答案 2 :(得分:2)
我猜C#的dynamic类型可以成为你的朋友。
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 ();
}
这里的关键是每个具体类都有不同的重载,并使用 动态 以无缝方式调用其中一个。美妙之处在于,在运行时解决了重载问题,使代码看起来很干净。
因为它是运行时类型解析,所以不执行编译时验证。假设您错过了一个具体类型的重载,并且运行时将 baseItem 解析为该特定的具体类型。然后它会导致运行时错误 - 崩溃 - 因为没有过载。
另一个问题是,动态在引擎盖下使用了Reflection。如您所知,Reflection会减慢您的应用程序。
答案 3 :(得分: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();
}
}
答案 4 :(得分: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();
}
//...
}