【问题标题】:Using an Dictionary<string, object> as Dictionary<string, Dictionary<string, string>>使用 Dictionary<string, object> 作为 Dictionary<string, Dictionary<string, string>>
【发布时间】:2012-03-01 02:38:56
【问题描述】:

在 C# 中,我需要将数据保存在字典对象中,如下所示:

Dictionary<string, Dictionary<string, string>> MyDict = 
    new Dictionary<string, Dictionary<string, string>>();

现在我意识到,在某些情况下,我需要一些其他(不是类似字典的)数据作为主 dict 的值。

如果我只是实例化主字典,是否有任何问题或限制。如:

Dictionary<string, object> MyDict = new Dictionary<string, object>();

我可以在对象字段中放置字符串、字典等等。

提前致谢, 最好的问候,史蒂文

【问题讨论】:

  • 标题与您的问题文本不匹配
  • 我认为这不是问题。您可能只需要在访问它时将其转换为应有的样子。
  • 你可以看到这个stackoverflow.com/questions/569903/multi-value-dictionary的答案是你想要的吗?
  • 这是一个很奇怪的要求。我的第一个建议是重新考虑设计,不是真的。问题中没有太多信息可以提出建议。否则我猜你可以维护两个单独的字典。如果没有看到 Oliver 的面向对象解决方案。到目前为止最好的。

标签: c# object dictionary


【解决方案1】:

是的,您的字典将不再是强类型的 - 在第一种方法中,您可以执行以下操作:

string value = myDict["foo"]["bar"];

在第二种方法中,这是不可能的,因为你必须先施法:

string value = ((Dictionary<string,string>)myDict["foo"])["bar"];

听起来您的问题可以通过更好的设计方法来解决。通常可以通过重新设计解决方案来避免在同一数据结构中存储不同类型的对象 - 那么为什么您需要这样做?

编辑:

如果您只想处理 null 值,您可以执行以下操作:

string value = myDict["foo"] != null ? myDict["foo"]["bar"] : null;

或者包裹在扩展方法中:

public static T GetValue<T>(this Dictionary<T, Dictionary<T,T>> dict, 
                            T key, T subKey) where T: class
{
    T value = dict[key] != null ? dict[key][subKey] : null;
    return value;
}

string value = myDict.GetValue("foo", "bar");

【讨论】:

  • 因为这是在大约 1000 行代码中实现的,并且在某些情况下需要添加带有 null 的值,其中键用作数据。比如:MyDict.Add("One_key", AnotherDictionary); MyDict.Add("Cool_key", null);比在 for 循环中: if(MyDict.value != null) //do something 你的观点是对的,设计可能有点错误!但是我现在需要数据的键和值字段,并且认为我不想为这些值为 null 的键值对 eintries 制作子字典,因为代码开销,如果你知道我的意思的话。 (许多具有空值的条目)
【解决方案2】:

你可以这样做。从主字典中检索数据后,您必须将结果转换为适当的类型:

object obj;
If(mainDict.TryGetValue("key", out obj)) {
    var dict = obj as Dictionary<string, string>>;
    if (dict != null) {
        // work with dict
    } else {
        var value = obj as MyOtherType;
        ....
    }
}

但请注意,这不是类型安全的;即,编译器只能部分检查您的代码关于 object 类型值的有效性。


或者,您可以尝试更面向对象的解决方案

public abstract class MyBaseClass 
{
    public abstract void DoSomething();
}

public class MyDictClass : MyBaseClass
{
    public readonly Dictionary<string, string> Dict = new Dictionary<string, string>();

    public override void DoSomething()
    {
        // So something with Dict
    }
}

public class MyTextClass : MyBaseClass
{
    public string Text { get; set; }

    public override void DoSomething()
    {
        // So something with Text
    }
}

然后声明你的主字典

var mainDict = new Dictionary<string, MyBaseClass>();

mainDict.Add("x", new MyDictClass());
mainDict.Add("y", new MyTextClass());

...

MyBaseClass result = mainDict[key];
result.DoSomething(); // Works for dict and text!

【讨论】:

    【解决方案3】:

    使用 object 作为字典中的值会带来一些风险和并发症:

    • 缺乏类型安全性(任何值都可以设置)
    • 您必须强制转换为特定类型,可能基于值

    您或许应该重新考虑您的设计。但是如果你真的想要灵活性,你可以创建一个新类型作为值类型。比如:

    class MySpecialType
    {
        public Dictionary<string, string> MyStringDictionary { get; set; }
        public string MyStringVal {get; set;}
    
        public Type ActiveType { get; set; } // property would specify the current type
        // ...
    

    您的主要字典声明将如下所示:

    Dictionary<string, MySpecialType> MyDict = new Dictionary<string, MySpecialType>();
    

    您可以使用 ActiveType 属性或创建一个指定类型的枚举。您还可以在类中包含静态 util 函数,这有助于返回正确的实例和类型...

    【讨论】:

    • 您的回答与其他人的知识相结合对我来说最有意义。 (谢谢!)“缺乏类型安全性(任何东西都可以设置为值)”在这种情况下对我来说是一个特性:D 你的类解决方案是有道理的,但有点像我试图的开销为我避免。如此解决,感谢大家,我的主要问题是代码的上下文和设计。 谢谢
    【解决方案4】:

    您将失去强类型及其所有好处。

    您能否创建一个具有 Dictionary 属性的新类并将您的其他数据添加到其中:

    public class CallItWhatYouLike
    {
      public Dictionary<string, string> Dictionary {get; set;}
      public int AnotherProperty {get; set;}
      ...
    }
    
    var MyDict = new Dictionary<string, CallItWhatYouLike>();
    

    【讨论】:

      【解决方案5】:

      不,没有问题。如果您需要将值键入为Dictionary&lt;string, string&gt;,只需强制转换即可解决此问题。

      【讨论】:

        【解决方案6】:

        好吧,您的代码的类型安全性会降低,您将需要运行时类型检查和类型转换,否则您可以使用 object 作为字典值类型并在其中存储任何类型。

        【讨论】:

          【解决方案7】:

          当你unboxSystem.Object 时,你会付出性能损失,但除此之外,你的方法没有问题,除了索引器的过度转换(由于弱类型 )。

          如果您使用 .NET 4,您可以考虑使用 System.Tuple

          【讨论】:

            猜你喜欢
            • 2014-10-22
            • 1970-01-01
            • 2012-09-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-28
            • 1970-01-01
            相关资源
            最近更新 更多