基类与子类值的字典兼容性

Posted

技术标签:

【中文标题】基类与子类值的字典兼容性【英文标题】:Dictionary compatibility of base class vs. subclass values 【发布时间】:2013-02-13 01:17:43 【问题描述】:

我有一个对象层次结构:

MyObject
+Variable
+etc.

(所以 MyObject 是基类,Variable 是子类之一)。

我有特定类型的字典

private ConcurrentDictionary<string, Variable> variables 
    = new ConcurrentDictionary<string, Variable>();

等等

我想把所有不同的列表放在一个高级词典中,在那里我可以找到所有特定的列表:

private Dictionary<Type, ConcurrentDictionary<string, MyObject>> objects 
    = new Dictionary<Type, ConcurrentDictionary<string, MyObject>>();

但我无法将特定词典添加到高级词典:

objects.Add(typeof(Variable), variables); // DOES NOT COMPILE

有没有办法做我想做的事?我不想将变量列表定义为

private ConcurrentDictionary<string, MyObject> variables 
    = new ConcurrentDictionary<string, MyObject>(); // WORKS, BUT NOT NICE TO USE

所以我想使用特定的列表来执行特定于类型的操作,而且还通过“对象”字典对所有对象类型启用通用操作,这样我就不需要为每个子类型手动编写所有代码。

例如,我想定义一个这样的方法:

    public List<Variable> GetVariables()
    
        return variables.Values.ToList();
    

所以当我知道它们都是变量时,我可以使用变量对象。

【问题讨论】:

当您添加项目时,您并没有添加密钥。 Add 方法接受一个键和一个值。您想要字典词典还是字典列表?我认为这里也有尝试的差异会失败。 你能告诉我当你尝试添加特定类型的字典时会发生什么,编译器错误是什么? 你的对象层次结构,你的意思是Variable是一个派生自MyObject的类吗? 对不起,我错过了钥匙。关键是类型,所以我可以获取特定类型的正确字典。 @Philipp M,是的,我就是这个意思。 【参考方案1】:

正如您在示例中看到的那样,您尝试完成的操作是不可能的,因为您试图将 ConcurrentDictionary&lt;string, Variable&gt; 类型的对象和 ConcurrentDictionary&lt;string, MyObject&gt; 类型的对象添加到具有强类型作为第二个参数的字典中的ConcurrentDictionary&lt;string, MyObject&gt;。因此,您不能添加第一种类型的对象。就像您想将 doublestring 作为第二个参数添加到 Dictionary&lt;int, string&gt; 对象时一样,这是不可能的。

但是有一个可行的解决方法。如果您的所有类型(MyObject, Variable 等)都来自同一个接口,那么您可以执行以下操作:

public interface MyInterface
          


public class MyObject:MyInterface



public class Variable:MyInterface


您可以调用此代码,类似于您想要的代码。当您检索所需的字典时,您可以将对象转换为特定类型或使用常用方法,多态性将达到其目的。

ConcurrentDictionary<string, MyInterface> myClass1Dict = new ConcurrentDictionary<string, MyInterface>();
myClass1Dict.TryAdd("one", new MyObject());
myClass1Dict.TryAdd("two", new MyObject());
ConcurrentDictionary<string, MyInterface> myClass2Dict = new ConcurrentDictionary<string, MyInterface>();
myClass1Dict.TryAdd("one", new Variable());
myClass1Dict.TryAdd("two", new Variable());
ConcurrentDictionary<Type, ConcurrentDictionary<string, MyInterface>> objectDict = new ConcurrentDictionary<Type, ConcurrentDictionary<string, MyInterface>>();
objectDict.TryAdd(Type.GetType(MyObject), myClass1Dict);
objectDict.TryAdd(Type.GetType(Variable), myClass2Dict);

【讨论】:

嗯,我不确定这是否有帮助。通过这些类,我还可以将每个字典定义为 。但是我只需要在特定类型和 MyObject 之间进行转换,当我知道我正在处理特定对象时,我想避免这种情况。 好吧,如果你的类有相同的方法和不同的实现(覆盖)而不是你不需要强制转换,那么你将能够在接口声明的对象和多态性上调用你想要的方法将完成其余的工作(调用确切的方法)。如果您的对象没有任何共同点,则可以使用 Dictionary 但您必须将这些对象转换为特定的字典。无论哪种方式,您都必须进行一些转换或重新设计您的类,或者不使用 Dictionary 而是使用简单的 ArrayList(或类似的)并具有一些索引类型映射。 嗯,这正是我试图克服的问题。我想将变量用作变量,但也处理我所有的列表是使用相同代码的通用方式。 恐怕这是不可能的,C# 是一种强类型语言,你可以用一些脚本代码做到这一点,但这里没有 这似乎是结论。感谢您的意见。

以上是关于基类与子类值的字典兼容性的主要内容,如果未能解决你的问题,请参考以下文章

python接口类与抽象类

Python3.7之抽象类与归一化

继承 接口 多态

day21

类型兼容---子类的对象可以给父类指针赋值

赋值兼容原则