简体   繁体   中英

Why my custom data type keeps converting into KeyValuePair in C#?

I have this kind of data type:

Dictionary<string, List<Dictionary<string, List<Dictionary<string, List<Dictionary<string, string>>>>>>>

and whenever I'm trying to reach the very bottom parts of it to count some stuff there I'm having an error that I can't use foreach on KeyValuePairs:

foreach statement cannot operate on variables of type 'KeyValuePair<string, List<Dictionary<string, List<Dictionary<string, string>>>>>' because 'KeyValuePair<string, List<Dictionary<string, List<Dictionary<string, string>>>>>' does not contain a public definition for 'GetEnumerator' [RestService]

Here's that part of loops:

void GetMetricsCount(List<Dictionary<string, List<Dictionary<string, List<Dictionary<string, string>>>>>> device, Dictionary<string, string> results_holder)
        {
            // count all metrics
            foreach (var type_element in device)
            {   
                foreach (var group_element in type_element)
                {   
                    foreach (var wtf in group_element)

Now it would be actually really good if there is any better way to deal with that kind of complicated data structures in C# and I would really appreciate if anyone tells me how because this is yuck!

UPDATE: I'm sorry for it but I've cut some code above while copying it here. Here's the answer to frustrations with non-matching types:

        // Get overview of metrics for last 24h
    public Dictionary<string, Dictionary<string, string>> GetMetricsOverview()
    {
        var overview_results = new Dictionary<string, Dictionary<string, string>>();

        // get total item count for each metric group and add to holder
        void GetMetricsCount(List<Dictionary<string, List<Dictionary<string, List<Dictionary<string, string>>>>>> device, Dictionary<string, string> results_holder)
        {
            // count all metrics
            foreach (var type_element in device)
            {   
                foreach (var group_element in type_element.Values)
                {   
                    foreach (var wtf in group_element)
                    results_holder.Add(group_element.Key + "_count", group_element.Value.Count.ToString());
                }
            }
            //
        }
        //

The outer loop looks like this:

foreach (var type_element in device)

With this loop, the type_element variable is a Dictionary<string, List<Dictionary<...>>> reference. It sounds like you're expecting to skip a level and go straight to the next List<Dictionary<...>> .

Maybe what you want is this:

foreach (var type_element in device)
{   
    foreach (var group_element in type_element.Values)

Here, type_element.Values is still a collection of Lists, so the group_element variable is still a List<Dictionary<string, List<Dictionary<string, string>>>> .

Just for completeness, that means the wtf variable at your next level is still a Dictionary<string, List<Dictionary<string, string>>> ... which is kind of crazy, if you think about it; the variable definitely lives up to its name. Are you sure you wouldn't rather define a class or two to get some compile-time type-safety around this data?

To get all the way to the inner-most Dictionary, you need this:

foreach (var type_element in device)
{ 
    foreach (var type_lists in type_element.Values)
    {   
        foreach(var group_element in type_lists)
        {
            foreach(var group_lists in group_element.Values)
            {
                 foreach (var wtf in group_lists.Values)
                 {
                      //...

You end up with a Dictionary<string, string> for the wtf variable. But again... this whole thing is kind of ridiculous. It looks a bit like you're trying to re-create a perfectly good type system using Dictionaries.

You may also want to look at the SelectMany() method, which can help reduce and simplify this code.

Perhaps you are trying to shoehorn Python idioms, especially associative object syntax ( item["property"] ), into .Net. This is a mistake. .Net doesn't really do associative objects. You want to actually define a class for this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM