简体   繁体   中英

Cast Dictionary<int, Object1> to Dictionary<int, Object2>

I have these 2 objects, a dictionary, and a method

public abstract  class Thing {}
public class Star : Thing {}

Dictionary<int, Star> dictStar;

public void listBoxAdd (Listbox listBox, Dictionary<int, Thing> thingDict){}

I want to call the method with dictStar. I tried a bunch of stuff to cast my dictionary and nothing I tried worked. I would think this should work, but the compiler disagrees.

listBoxAdd (starList, ( Dictionary<int, Thing>) dictStar);

I get an error CS0030 that c# can not convert a dictionary of star to a dictionary of thing.

There are several other classes based on thing and my design requires dictionaries of them being passed to methods that will work on the fields in Thing. There are several times I have methods that only need to access stuff that is defined in Thing.

I have no problem casting a Star to a Thing, but I have the problem with the dictionary. I tried having the method take a dictionary of int, object and I could call but in the method I could not cast the Dictionary of Objects to Tings.

If I use Star Dictionaries in both the method and call it works fine.

I even use a base class of Thing with Star derived from it.

I come from the old days of 64K mainframes and am constantly thinking of memory usage and machine cycles so, in addition to being inelegant, going through the dictionary and calling with every element, though it will work, seems like a bad idea.

I know a lot of the rules are used to allow c# to clean up unused stuff in memory, but there is no danger of the elements going away during the call.

I will explain why it is forbidden by C#. Let's define a second subclass public class BlackHole: Thing {}

Now if you could cast the dictionary of stars into a dictionary of things as you try var dicThings = (Dictionary<int, Thing>) dictStar

You could write later dicThings.Add(5, new BlackHole()); , but there is an issue with that: the runtime type of dicThings would still be a dictionary of stars... containing a black hole.


Solution:

You can turn your method into a generic with a constraint on the type, as such listBoxAdd<T>.... where T: Thing


Here is a full example code:

using System;
using System.Collections.Generic;

public class Program
{
    public abstract  class Thing {}
    public class Star : Thing {}
    public class BlackHole : Thing {}

    public static void DoThing (Dictionary<int, Thing> thingDict) { Console.WriteLine("DoThing"); }

    public static void DoThingMagic<T> (Dictionary<int, T> thingDict) where T : Thing { Console.WriteLine("DoThingMagic"); }

    public static void Main()
    {
        Dictionary<int, Star> dictStars = new Dictionary<int, Star>();

        // line below has a compilation error to protect you from mixing stars with black holes ;)
        Dictionary<int, Thing> dictThings = (Dictionary<int, Thing>) dictStars;
        // it explains the method call has a compilation error too:
        DoThing(dictStars);

        // now this method call will compile and execute:
        DoThingMagic(dictStars);
    }
}

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