[英]C# store different child classes and call them at same time
Actually all these classes are defined in the 3rd lib, so I can't change them.实际上所有这些类都在第三个库中定义,所以我无法更改它们。
===================== =====================
I'm learning C# and I met a problem.我在学习C#,遇到了一个问题。 Suppose I have a parent class and two child classes:
假设我有一个父类 class 和两个子类:
class ParentClass
{
....
};
class ChildA : ParentClass
{
public string name;
};
class ChildB : ParentClass
{
public string name;
};
Both class ChildA and ChildB have property name
, but ParentClass doesn't. class ChildA 和 ChildB 都有属性
name
,但 ParentClass 没有。 Now I need to store ChildA and ChildB in a dictionary, so I write Dictionary<string, ParentClass>
.现在我需要将 ChildA 和 ChildB 存储在字典中,所以我写了
Dictionary<string, ParentClass>
。
But I can't get name because ParentClass doesn't have this property:但我无法获取名称,因为 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?
}
how can I handle this?我该如何处理?
The short version is "no".简短的版本是“否”。 There are things that you could do if you have access to the types - for example, you could implement a common interface (
interface IHazName { public string Name {get;} }
) - but you can't do that here since you don't control the types.如果您有权访问这些类型,您可以做一些事情 - 例如,您可以实现一个通用接口(
interface IHazName { public string Name {get;} }
) - 但你不能在这里这样做,因为你没有控制类型。
A lazy way could be to abuse dynamic
:一种懒惰的方法可能是滥用
dynamic
:
dynamic hack = pc;
hack.name = "yolo";
but... please don't!但是……请不要! Your
is
approach (or perhaps a switch
expression) is about as good as you can get.您
is
方法(或者可能是switch
表达式)与您所能获得的一样好。 Note that if you need to talk to this member in a lot of places, you could move that shared logic to an extension method:请注意,如果您需要在很多地方与该成员交谈,您可以将该共享逻辑移至扩展方法:
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());
}
(or a similar set method) - then at least you don't need to repeat yourself. (或类似的设置方法)——那么至少你不需要重复自己。
One way to do this is to use reflection on the type to determine if it has a "name" property (or field, as you've shown):一种方法是对类型使用反射来确定它是否具有“名称”属性(或字段,如您所示):
public static string GetName(ParentClass parent)
{
return parent.GetType().GetProperty("name")?.GetValue(parent, null).ToString()
?? parent.GetType().GetField("name")?.GetValue(parent).ToString();
}
Example usage:用法示例:
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("\n\nDone. Press any key to exit...");
Console.ReadKey();
}
Output Output
Parent name:
Child name: ChildName
Done. Press any key to exit...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.