2015-10-25 66 views
0

我有一个C#程序,我需要查找基于键的数据。 我将我的Python代码移植到C#中,发现难以实现嵌套Python字典的等效功能。经过多次尝试使用C#字典后,我决定使用Hashtable,因为它是松散类型的。如何访问C#中的嵌套散列表值

我可以写入我的嵌套Hashtable结构,如果迭代,我可以读取它。但我想要做的是访问基于特定键的特定数据。

这里是我使用的代码,它的工作原理:

 foreach (DictionaryEntry x in ParameterTypes) 
     { 
      Console.WriteLine(x.Key + " -- "); 
      foreach (DictionaryEntry y in x.Value as Hashtable) 
      { 
       Console.WriteLine(y.Key + ": " + y.Value); 
      } 
      Console.WriteLine("\n"); 
     } 

它给了我这个输出(样本):

EVENT_PARAM_SCTP_SHUTDOWN_RESULT -
名称:EVENT_PARAM_SCTP_SHUTDOWN_RESULT
usevalid:是
说明:SCTP关机结果
numberofbytes:1
type:ENU中号

EVENT_PARAM_ENBS1APID -
名:EVENT_PARAM_ENBS1APID
numberofbytes:3
usevalid:是
描述:eNB的S1 AP ID
分辨率:1
类型:UINT

然而,以下代码不起作用:

Console.WriteLine(ParameterTypes["EVENT_PARAM_ENBS1APID"]["description"]); 

当我试图获取基于键和嵌套键的数据时,正确的方法是什么?

+1

您应该切换到'DIivingary ' – SLaks

+0

我花了整整一天的时间试图使用字典,并放弃了,去散列表,而不是宽松的打字。我的密钥可能会有所不同,值的类型可能会有所不同,并且在某些情况下,我有第三级嵌套,为了清晰起见,此处未显示。 – hacker101

+1

这听起来像个糟糕的主意。你应该重新考虑你的设计是更安全的。 – SLaks

回答

0

这段代码产生你似乎期望输出...

using System; 
using System.Collections; 
using System.Collections.Generic; 

namespace TestProject 
{ 
    /// <summary> 
    /// Parameter entry for ParameterTypes collection. 
    /// </summary> 
    class ParameterEntry : Dictionary<string, object> 
    { 
     // this is just an subclassed Dictionary class 
    } 

    /// <summary> 
    /// Parameter types collection. 
    /// </summary> 
    class ParameterTypes : Dictionary<string, ParameterEntry> 
    { 
     // this class is a Dictionary that holds ParameterEntry objects 

     /// <summary> 
     /// Add the specified value using its name as the key. 
     /// </summary> 
     /// <param name='value'> 
     /// A parameter entry. 
     /// </param> 
     public void Add(ParameterEntry value) 
     { 
      string key = (string)value["name"]; 
      this.Add(key, value); 
     } 
    } 

    class TestProject 
    { 
     public static void Main (string[] args) 
     { 
      var entry1 = new ParameterEntry(); 
      entry1.Add("name", "EVENT_PARAM_SCTP_SHUTDOWN_RESULT"); 
      entry1.Add("usevalid", "Yes"); 
      entry1.Add("description", "The results of a SCTP Shutdown"); 
      entry1.Add("numberofbytes", 1); 
      entry1.Add("type", "ENUM"); 

      var entry2 = new ParameterEntry(); 
      entry2.Add("name", "EVENT_PARAM_ENBS1APID"); 
      entry2.Add("numberofbytes", 3); 
      entry2.Add("usevalid", "Yes"); 
      entry2.Add("description", "eNB S1 AP ID"); 
      entry2.Add("resolution", 1); 
      entry2.Add("type", "UINT"); 

      var types = new ParameterTypes(); 
      types.Add(entry1); 
      types.Add(entry2); 

      Console.WriteLine(types["EVENT_PARAM_ENBS1APID"]["name"]); 
      Console.WriteLine(types["EVENT_PARAM_ENBS1APID"]["numberofbytes"]); 
      Console.WriteLine(types["EVENT_PARAM_ENBS1APID"]["usevalid"]); 
      Console.WriteLine(types["EVENT_PARAM_ENBS1APID"]["description"]); 
     } 
    } 
} 

你当然可以嵌套Dictionary一个Dictionary中,你可以使用字符串作为主键和嵌套按键,并使用一个对象作为最终的嵌套值。您也可以将类型为Dictionary<>的类作为您自己的类进行分类,以抽象实现并使代码更易于阅读和理解。请记住,如果你来自Python或任何其他松散类型的语言,则必须重新考虑如何用C#等强类型语言来解决问题。

+0

这真是太棒了,我喜欢它看到几行类定义可以做到这么多真的让我感兴趣并有动力采用新的思维方式,将代码和概念融入到我的项目中,并且工作得很好,代码精简而干净,非常感谢! – hacker101

1

尝试使用通用字典类型字典,所以你可以存储嵌套集合:

 Dictionary<string,object> ParameterTypes = new Dictionary<string,object>(); 
    //Populate the parameterTypes here 
    foreach (var x in ParameterTypes) 
    { 
     Console.WriteLine(x.Key + " -- "); 
     foreach (var in x.Value) 
     { 
      Console.WriteLine(y.Key + ": " + y.Value); 
     } 
     Console.WriteLine("\n"); 
    } 

如果您已经定义,你可以使用它的价值类:

Dictionary<string, Dictionary<string,YourType>> or similar 
+0

请参阅响应SLaks的评论。字典不提供足够的灵活性(强类型),我认为散列表会更直接(松散类型)。我也看到了一些关于使用类的stackexchange问​​答。对于在Python或Perl中出现一个简单而常见的东西似乎有点深刻,但是可能有一个类“ParameterTypes”并创建它的集合将是解决方案。我希望有一些简单的东西(我不是专业的程序员)。 – hacker101

+0

然后,你可能想尝试在c#中的动态类型https://msdn.microsoft.com/en-us/library/dd264736.aspx –

+1

我早些时候尝试过,但必须得到的语法错误。我会再次尝试,更仔细。 – hacker101

2

我同意其他响应者,你应该重新考虑这个结构,而不是试图模仿PHP。但如果你想坚持下去,你的双重索引不起作用的原因是因为ParameterTypes["EVENT_PARAM_ENBS1APID"]返回一个object,它没有[]运算符。你必须把它作为一个Hashtable来重新索引。

首先,您可能需要使用is运算符来确定给定节点是否确实是嵌套哈希表。如果是,你可以去

((Hashtable) ParameterTypes["EVENT_PARAM_ENBS1APID"])["description"] 

(ParameterTypes["EVENT_PARAM_ENBS1APID"] as Hashtable)["description"] 
+0

如何正确投射。语法是什么?我试过但失败:( – hacker101

+0

使用提供的语法,试图将值赋给一个字符串(打印到控制台)给我一个错误“Error 不能隐式地将类型'object'转换为'string'。转换是否存在(是否缺少演员?)“。但是当我把(字符串)放在控制台前面时,会给我一个空白结果。例如: string result =(string)((Hashtable)ParameterTypes [”EVENT_PARAM_ENBS1APID“ ])[“description”]; – hacker101

+0

@ hacker101我不知道为什么你会得到一个空白的结果 –