3

To simplify using a specific type of dictionary I have derived a class from the generic Dictionary<> to handle assorted elements derived from a common base class:

//my base class holding a value
public abstract class A{ public int aValue; }

//derived classes that actually are stuffed into the dictionary
public class B : A {...}
public class C : A {...}

//wrapper class for dictionary
public class MyDict : Dictionary<string, A>;

//my class using the dictionary
public class MyClass {

  public MyDict dict = new MyDict();//use an instance of MyDict

  public MyClass() { ... //fill dict with instances of B and C }

  //function to return all elements of dict having a given value
  public MyDict GetSubSet(int testVal) {
    var ret = dict.Where(e => e.Value.aValue == testVal).
                       ToDictionary(k => k.Key, k => k.Value);
    return (MyDict) ret; // <- here I get a runtime InvalidCastException
  }
}

Before wrapping the generic Dictionary in the MyDict-class the cast succeeded (if I replace all instances of MyDict with Dictionary<string,int>, the code works fine, even without casting in the return statement).

I have also tried to cast the result using return ret as MyDict; but that will return a null value. Casting through object like this: return (MyDict) (object) ret; also fails with an InvalidCastException.

Anybody have an idea how to cast/convert the return value correctly?

AstaDev
  • 149
  • 1
  • 8

1 Answers1

7

You get an invalid cast exception because the result of ToDictionary is not MyDict. In order to fix this problem, add a constructor to MyDict that takes an IDictionary<string,A>, and return the result of calling that constructor from your GetSubSet method:

public class MyDict : Dictionary<string, A> {
    public MyDict() {
        // Perform the default initialization here
        ...
    }
    public MyDict(IDictionary<string,A> dict): base(dict) {
        // Initialize with data from the dict if necessary
        ...
    }
}
...
public MyDict GetSubSet(int testVal) {
    var ret = dict.Where(e => e.Value.aValue == testVal).
                   ToDictionary(k => k.Key, k => k.Value);
    return new MyDict(ret);
}
Alexsandro
  • 1,191
  • 1
  • 14
  • 22
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks for that hint, it works. But I was trying to find a way to avoid copying the dictionary because of the performance impact it has. Is there no way to use the `Dictionary` that is returned by `ToDictionary(...)` directly as a return value? – AstaDev Jun 06 '13 at 07:04
  • @AstaDev Making `new MyDict` does not copy anything, because dictionaries are passed by reference. It uses the return value of `ToDictionary` directly, without making a copy - it just puts a wrapper around it. – Sergey Kalinichenko Jun 18 '13 at 09:07