问题已澄清新线程:在具有超类输入的泛型方法中访问子类属性
我有一个a级
子类B、C和D继承自A.
每个子类有3个子类a、b和c。
a、 a、b和c具有唯一属性的列表。
然而,现在我想构建一个通用函数来访问这些属性,那么在不打开Type的情况下如何做到这一点呢?
澄清:我不希望a:B有抽象的C方法/属性
示例:
public void Method(A a){
if(a.isSubClassOf(B))
{Console.WriteLine(a.BaProperty);}
if(a.isSubClassOf(C))
{Console.WriteLine(a.CbProperty);}
if(a.isSubClassOf(D))
{Console.WriteLine(a.DcProperty);}
}
如果不强制转换为派生类,就不能在派生类中定义成员并通过对基类的引用访问它:
class A {}
class B
{
public int i;
}
A a = new B();
a.i = 0; // error
((B)a).i = 0; // OK
在层次结构中的任何基类型中声明虚拟属性,或者使用转换为具体派生类型。当然,在第二种情况下,您的方法没有任何意义。
通常,您会使用在A
中定义并在子类中重写的virtual
或abstract
方法。
public abstract class A
{
protected abstract PropertyType PropertyValue {get;}
public void Method()
{
Console.WriteLine(PropertyValue);
}
}
public class B : A
{
protected override PropertyType Property { get { return PropertyType.B; } }
}
// etc...
一个优雅的解决方案是覆盖ToString
public abstract class A { }
public class B : A {
public int b { get; set; }
public override string ToString()
{
return b.ToString();
}
}
// Do the same with C and D ....
A[] array = new A[] { new B(), new C(), new D() };
foreach (A a in array) {
Console.WriteLine(a);
}
注意,Console.WriteLine
不需要知道A
中的特殊方法或属性。它也适用于非从A
派生的类型。
这在很大程度上取决于您真正想要实现的目标。在某些情况下,Steve Czetty的建议是最好的选择。
在其他情况下,你可以保持所有属性的不同,并在基类中有一个虚拟方法,例如,在这种情况下,它会返回一个"字符串",然后你可以在控制台中编写它或任何你想要的东西。
编辑:您可以按照Olivier的建议覆盖ToString。但只有当你感觉到你要返回的是"对象的字符串表示"时。
公共摘要A类{公共字符串PropertyA{get;set;}
public virtual string GetString() //
{
return PropertyA;
}
}
public class B:A
{
public string PropertyB { get; set; }
public override string GetString()
{
return PropertyB;
}
}
public class C:A
{
public string PropertyC { get; set; }
public override string GetString()
{
return string.Format("{0} - {1}", base.GetString(), PropertyC) // for example if you wanted to do something more complex
}
}
现在,如果你需要的东西不能像这样解决,你可以扮演丹尼斯建议。
还有另一种可能性:您可以使用访问者模式。在这里你可以找到几种实现它的方法
只是为了让你有一个想法,你最终会有一个类似的课程:(这将取决于你真正想要实现的目标)您必须实现一些其他基本的东西(接口和一些方法),但从基类的引用中,您将能够轻松地调用相应的"Visit"方法。我添加的链接中有很多细节。
class ClassicVisitor : IAVisitor
{
public string SuperComplexStringResult { get;set; }
public void Visit(B b) { SuperComplexStringResult = String.Format("Super Complex Stuff + {0}", b.PropertyB); }
public void Visit(C c) { SuperComplexStringResult = String.Format("Super Complex Stuff + {0}", c.PropertyC); }
}