C# 从C中的基类访问派生类的属性#
在C#中,当泛型列表仅包含基类时,访问派生类属性的最佳方法是什么C# 从C中的基类访问派生类的属性#,c#,generics,collections,C#,Generics,Collections,在C#中,当泛型列表仅包含基类时,访问派生类属性的最佳方法是什么 public class ClassA : BaseClass { public object PropertyA { get; set; } } public class ClassB: BaseClass { public object PropertyB { get; set; } } public class BaseClass { } public void Main { List<Ba
public class ClassA : BaseClass
{
public object PropertyA { get; set; }
}
public class ClassB: BaseClass
{
public object PropertyB { get; set; }
}
public class BaseClass
{
}
public void Main
{
List<BaseClass> MyList = new List<BaseClass>();
ClassA a = new ClassA();
ClassB b = new ClassB();
MyList.Add(a);
MyList.Add(b);
for(int i = 0; i < MyList.Count; i++)
{
//I would like to access PropertyA abd PropertyB from the derived classes
}
}
公共类ClassA:基类
{
公共对象属性{get;set;}
}
公共类ClassB:基类
{
公共对象属性b{get;set;}
}
公共类基类
{
}
公共排水干管
{
List MyList=新列表();
ClassA=新ClassA();
ClassB=新的ClassB();
添加(a);
添加(b);
for(int i=0;i
整个前提都没有意义-a实例的属性B是什么
如果执行手动运行时类型检查(inst是Foo),然后使用所需的属性强制转换为类型,则可以执行此操作。泛型和子类可能存在一些问题(在这种情况下,应返回System.Collections.ArrayList),但必须将基类强制转换为要使用的子类。如果您使用'as'目录,如果基类可以强制转换为子类,那么它将成功;如果不能强制转换,那么它将为null。它看起来像:
BaseClass o = MyList[i];
if (o is ClassB)
{
object k = ((ClassB)o).PropertyB;
}
if (o is ClassA))
{
object j = ((ClassA)o).PropertyA;
}
for(int i = 0; i < MyList.Count; i++)
{
BaseClass bc = MyList[i];
ClassA a = bc as ClassA;
ClassB b = bc as ClassB;
bc.BaseClassMethod();
if (a != null) {
a.PropertyA;
}
if (b != null) {
b.PropertyB;
}
}
public class BaseClass
{
public virtual void DoStuff() { }
}
public class ClassA : BaseClass
{
public object PropertyA { get; set; }
public override void DoStuff()
{
// do stuff with PropertyA
}
}
public class ClassB : BaseClass
{
public object PropertyB { get; set; }
public override void DoStuff()
{
// do stuff with PropertyB
}
}
for(int i=0;i
还有,我应该提一下,这闻起来有点难闻。这类代码表示结构不良的对象继承权。一般来说,如果不能说a是基类,那么您的设计可能是错误的。但是,希望这有帮助 你当然可以沮丧,就像这样:
for (int i = 0; i < MyList.Count; i++)
{
if (MyList[i] is ClassA)
{
var a = ((ClassA)MyList[i]).PropertyA;
// do stuff with a
}
if (MyList[i] is ClassB)
{
var b = ((ClassB)MyList[i]).PropertyB;
// do stuff with b
}
}
如果您经常这样做,另一个选择是在列表上创建一个扩展方法,以返回正确类型的枚举。i、 e
public static class MyBaseListExtensions
{
public static IEnumerable<ClassA> GetAllAs(this List<MyBaseClass> list)
{
foreach (var obj in list)
{
if (obj is ClassA)
{
yield return (ClassA)obj;
}
}
}
public static IEnumerable<ClassB> GetAllbs(this List<MyBaseClass> list)
{
foreach (var obj in list)
{
if (obj is ClassB)
{
yield return (ClassB)obj;
}
}
}
}
公共静态类MyBaseListExtensions
{
公共静态IEnumerable GetAllAs(此列表)
{
foreach(列表中的var obj)
{
if(obj为A类)
{
收益率回报(A类)obj;
}
}
}
公共静态IEnumerable GetAllbs(此列表)
{
foreach(列表中的var obj)
{
if(obj为B类)
{
收益率回报率(B类)obj;
}
}
}
}
然后你可以像……一样使用它
private void button1_Click(object sender, EventArgs e)
{
ClassA a1 = new ClassA() { PropertyA = "Tim" };
ClassA a2 = new ClassA() { PropertyA = "Pip" };
ClassB b1 = new ClassB() { PropertyB = "Alex" };
ClassB b2 = new ClassB() { PropertyB = "Rachel" };
List<MyBaseClass> list = new List<MyBaseClass>();
list.Add(a1);
list.Add(a2);
list.Add(b1);
list.Add(b2);
foreach (var a in list.GetAllAs())
{
listBox1.Items.Add(a.PropertyA);
}
foreach (var b in list.GetAllbs())
{
listBox2.Items.Add(b.PropertyB);
}
}
private void按钮1\u单击(对象发送者,事件参数e)
{
ClassA a1=新的ClassA(){PropertyA=“Tim”};
ClassA a2=新的ClassA(){PropertyA=“Pip”};
ClassB b1=新的ClassB(){PropertyB=“Alex”};
ClassB b2=新的ClassB(){PropertyB=“Rachel”};
列表=新列表();
增加(a1);
增加(a2);
列表。添加(b1);
列表。添加(b2);
foreach(list.GetAllAs()中的var a)
{
列表框1.Items.Add(a.PropertyA);
}
foreach(list.GetAllbs()中的变量b)
{
列表框2.Items.Add(b.PropertyB);
}
}
您需要在基类中将属性声明为virtual,然后在派生类中重写它们
例:
公共类ClassA:基类
{
公共重写对象属性{get;set;}
}
公共类ClassB:基类
{
公共重写对象属性b{get;set;}
}
公共类基类
{
公共虚拟对象属性{get;set;}
公共虚拟对象属性b{get;set;}
}
公共排水干管
{
List MyList=新列表();
ClassA=新ClassA();
ClassB=新的ClassB();
添加(a);
添加(b);
for(int i=0;i
您可能需要在基类中实现该属性以返回默认值(例如null),或者将其抽象并强制所有派生类实现这两个属性
您还应该注意,通过在两个派生类中重写它并返回不同的值,您可以为例如PropertyA返回不同的内容。继TimJ的答案之后,您可以编写一个扩展方法,该方法适用于所有类型:
public static IEnumerable<T> OfType<T>(this IEnumerable list)
{
foreach (var obj in list)
{
if (obj is T)
yield return (T)obj;
}
}
类型的公共静态IEnumerable(此IEnumerable列表)
{
foreach(列表中的var obj)
{
if(obj是T)
收益率(T)obj;
}
}
或者,如果您有Linq,则该函数位于命名空间系统中。Linq。我使用第二个代码示例访问派生类中的属性……感谢您的输入。这太棒了。我到处搜索,发现这么多线程都说这是不可能的,但这个解决方案非常有效。我肯定遗漏了一些东西,但是如果您只是想在派生类中编写,为什么需要
BaseClass
中的DoStuff()
?您是否可以使用接口强制在派生类中包含DoStuff()
?@SteveCinq,因为这样,您就可以在基类对象上调用该方法,而不必知道该类的确切派生类型。
public static IEnumerable<T> OfType<T>(this IEnumerable list)
{
foreach (var obj in list)
{
if (obj is T)
yield return (T)obj;
}
}