实际上所有这些类都是在第3个库中定义的,所以我不能更改它们。
=====================
我正在学习c#,我遇到了一个问题。假设我有一个父类和两个子类:
class ParentClass
{
....
};
class ChildA : ParentClass
{
public string name;
};
class ChildB : ParentClass
{
public string name;
};
类ChildA和ChildB都有属性name
,但ParentClass没有。现在我需要将ChildA和ChildB存储在一个字典中,所以我写Dictionary<string, ParentClass>
。
但是我不能得到name因为ParentClass没有这个属性:
foreach (ParentClass pc in dict.Values)
{
// it works, but too verbose as I may have ChildC, ChildD...
if (pc is ChildA ca)
{
ca.name
}
if (pc is ChildB cb)
{
cb.name
}
// how can I get the name property at same time?
}
我该如何处理这个?
简写为"no"。如果您可以访问类型,可以做一些事情—例如,您可以实现一个公共接口(interface IHazName { public string Name {get;} }
)—但是您不能在这里这样做,因为您不控制类型。
一种偷懒的方法可能是滥用dynamic
:
dynamic hack = pc;
hack.name = "yolo";
但是…请不要!您的is
方法(或者可能是switch
表达式)是您所能得到的最好的方法。注意,如果您需要在很多地方与该成员进行通信,您可以将共享逻辑移动到扩展方法:
static class SomeUtilsType {
public static string GetName(this ParentClass obj) => obj switch {
ChildA ca => ca.name,
ChildB cb => cb.name,
_ => throw new ArgumentException("Unexpected object type", nameof(obj)),
};
}
...
foreach (ParentClass pc in dict.Values)
{
Console.WriteLine(pc.GetName());
}
(或类似的set方法)-那么至少你不需要重复你自己。
这样做的一种方法是对类型使用反射来确定它是否有"名称";属性(或字段,如您所示):
public static string GetName(ParentClass parent)
{
return parent.GetType().GetProperty("name")?.GetValue(parent, null).ToString()
?? parent.GetType().GetField("name")?.GetValue(parent).ToString();
}
使用例子:
static void Main(string[] args)
{
ParentClass parent = new ParentClass();
ChildA child = new ChildA { name = "ChildName" };
Console.WriteLine($"Parent name: {GetName(parent)}");
Console.WriteLine($"Child name: {GetName(child)}");
Console.Write("nnDone. Press any key to exit...");
Console.ReadKey();
}
输出Parent name:
Child name: ChildName
Done. Press any key to exit...