hacker101 hacker101 - 29 days ago 11
C# Question

How to access a nested hashtable value in C#

I have a C# program where I need to lookup data based on keys.
I am porting my Python code to C# and finding it difficult to implement the equivalent of nested Python dictionaries. After many attempts at using C# Dictionaries, I settled on Hashtable because it is loosely typed.

I am able to write to my nested Hashtable structure, and I can read from it if I iterate. But what I want to do is access specific data based on specific keys.

Here is the code I am using, which works:

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");
}


It gives me this output (sample):

EVENT_PARAM_SCTP_SHUTDOWN_RESULT --

name: EVENT_PARAM_SCTP_SHUTDOWN_RESULT

usevalid: Yes

description: The results of a SCTP Shutdown

numberofbytes: 1

type: ENUM




EVENT_PARAM_ENBS1APID --

name: EVENT_PARAM_ENBS1APID

numberofbytes: 3

usevalid: Yes

description: eNB S1 AP ID

resolution: 1

type: UINT


However, this code below doesn't work:

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


What is the proper way to get data based on the key and nested key as I am attempting?

Answer

This code produces the output you seem to expect...

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"]);
        }
    }
}

You can certainly nest a Dictionary within a Dictionary and you can use strings as the primary keys and nested keys and use an object as the final nested value. You can also subclass the typed Dictionary<> class as your own class to abstract the implementation and make the code easier to read and understand. Keep in mind that if you're coming from Python or any other loosely-typed language, you have to re-think how you're approaching the problem in terms of a strongly-typed language like C#.