简体   繁体   中英

Casting Dictionaries in C#

I have the following property declared in my C# class, that we'll call MyMainClass:

    private Dictionary<int, Dictionary<int, Dictionary<int, MyOtherClass>>> _oMyObjByTypeIDPeriodIDStatusID = null;
    public Dictionary<int, Dictionary<int, Dictionary<int, MyOtherClass>>> oMyObjByTypeIDPeriodIDStatusID
    {
        get
        {
            return _oMyObjByTypeIDPeriodIDStatusID;
        }
        set
        {
            _oMyObjByTypeIDPeriodIDStatusID = value;
        }
    }

Sometimes, through reflection I'll run something like:

    string propName = "oMyObjByTypeIDPeriodIDStatusID[2][4[6]";
    object o = GetReflectedProperty(oMyMainClass, propName);

But that won't work because of the indexing, so instead I'll strip out the indexes and throw them in an int array. Then I run

    int idxs = new int[] {2,4,6};
    string propName = "oMyObjByTypeIDPeriodIDStatusID";
    object o = GetReflectedProperty(oMyMainClass, propName);

That works, but now I have an object, whose value is of type

    Dictionary<int, Dictionary<int, Dictionary<int, MyOtherClass>>>

And now I somehow have to traverse through each index until I finally get to the last nested Dictionary and the instance of MyOtherClass. I tried the following code:

    for (int i = 0; i < idxs.Length; i++)
        o = ((Dictionary<int, object>)o)[idxs[i]];        

But that throws an error that it can't cast

    Dictionary<int, Dictionary<int, Dictionary<int, MyOtherClass>>> 

into

    Dictionary<int, object>

which makes sense. My problem is, this code is generic, so I don't know what type it will be. In other words, I use it for different properties, so I don't know how many nested dictionaries there will be, so how can I cast it properly?

You could just cast it to an IDictionary , if you don't know the generic type parameters at compile-time.

Just like Dictionary<TKey, TValue> , IDictionary has an indexer , so you should be able to iterate through the inner dictionaries using that interface.

If you break apart going through the layers to two steps, one to go through the nested dictionaries and one to get the final value you can use the non-generic interface IDictonary and change your for loop to

for (int i = 0; i < idxs.Length - 1; i++)
    o = ((IDictionary)o)[idxs[i]];

o = ((IDictionary)o)[idxs[idxs.Length - 1]];

and that should fix your casting errors.

The real issue here is that Dictionary<TKey,TValue> is strongly typed, so the system doesn't recognize it as Dictionary<int,object> even though TValue is derived from object. Try this instead (using Linq):

var recastDictionary = o
    .Select(x => new { Key = x.Key, Value = (object)x})
    .ToDictionary(x => x.Key, x => x.Value)
;

That should recast the values and give you a Dictionary<int,object> without any hassle or loss of data. (I'm sure there's more efficient ways to do it, but that should be acceptable enough, or at least give you an idea of what you need to do.)

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