3

If it exists, what is the C# equivalent of the following Java code:

new HashMap<Class<? extends BaseClass>, Integer>();

I currently use new Dictionary<Type, int>(), which is more like
new HashMap<Class<?>, Integer>() which is obviously not the same.

(Ignore the differences between HashMap and Dictionary)

Edit: To clarify, I am not trying to define a new class, simply create an instance of HashMap/Dictionary.

Acidic
  • 6,154
  • 12
  • 46
  • 80
  • 1
    Possible duplicate http://stackoverflow.com/questions/4732494/cs-equivalent-of-javas-extends-base-in-generics – halex Oct 12 '12 at 19:22
  • @halex I saw that question and it's similar - but it's definitely not the same. – Acidic Oct 12 '12 at 19:52

3 Answers3

3

I believe you want to constrain type parameters to generic types - the where keyword is used for that:

class MyDict<TKey, TValue> : Dictionary<TKey, TValue> where TValue : SomeBaseClass
{
    ...
}

Is this what you're asking for or am I misunderstanding your question?

Edit: you cannot do exactly what you ask for in C# - you can't define an local instance of a generic type with a type constraint. You can, however, pre-declare your constrained Dictionary type (like my example) and then create an instance of that type like so:

// SomeClass will have to inherit from SomeBaseClass
MyDict<SomeClass> instance = new MyDict<SomeClass> ();

I think this is close to what you're looking for. Post a comment if I misunderstand it - I don't know Java this deep.

xxbbcc
  • 16,930
  • 5
  • 50
  • 83
  • The OP is not declaring a class... what he's trying to do is not possible in C# – Thomas Levesque Oct 12 '12 at 19:24
  • @ThomasLevesque You seem to be right - after the edit, it seems to be a function call. – xxbbcc Oct 12 '12 at 19:29
  • What I am trying to do is have a `Dictionary` with `Type` as key, but not just any type - only `Type` from classes that derive from a certain base class. – Acidic Oct 12 '12 at 19:47
  • @Acidic I see - you can't do that declaratively in C# - you can only do a runtime check then, like in Jordão's answer. I misunderstood what you were looking for. – xxbbcc Oct 12 '12 at 19:53
3

There is no equivalent of the Java wildcard in C#. In Java, the type for types is Class<T> where T is the class itself. The equivalent in C# is the type Type, which is not generic. So it seems that the best you can do is to have, as you said, a Dictionary<Type, int>, and if it's encapsulated in a class you can restrict what you put in the dictionary in the code (so it will just be a runtime check):

private Dictionary<Type, int> myDictionary = new Dictionary<Type, int>();
public void Add(Type type, int number) {
   if (!typeof(BaseClass).IsAssignableFrom(type)) throw new Exception();
   myDictionary.Add(type, number);
}

You can even implement your own IDictionary with that logic.

UPDATE

Another runtime trick I can think of is to use a wrapper class for your types:

public class TypeWrapper<T>
{
    public Type Type { get; private set; }
    public TypeWrapper(Type t)
    {
        if (!typeof(T).IsAssignableFrom(t)) throw new Exception();
        Type = t;
    }
    public static implicit operator TypeWrapper<T>(Type t) {
        return new TypeWrapper<T>(t);
    }
}

(Also implement Equals and GetHashCode, just delegate to Type.)

And then your dictionary becomes:

var d = new Dictionary<TypeWrapper<BaseClass>, int>();
d.Add(typeof(BaseClass), 2);
d.Add(typeof(Child), 3);
Jordão
  • 55,340
  • 13
  • 112
  • 144
  • You pretty much hit the nail on the head. What I would like to have is compile time checking, or at the very least have runtime checking without having to right a lot of extra code or create new types. From the answers it seems that there really is no equivalent of this in C#... That's a shame. – Acidic Oct 12 '12 at 19:49
0

Was looking into this same problem and this poor man's checker is the best thing I could come up with:

class MyValue {
    public Type Type { get; private set; }

    private MyValue(Type type)
    {
        this.Type = type;
    }

    public MyValue of<T>() where T : BaseClass
    {
        return new MyValue(typeof(T));
    }
}

IDictionary<int, MyValue> myDictionary = new Dictionary<int, MyValue>()
{
    { 1, MyValue.of<SubClass1>(); },
    { 2, MyValue.of<SubClass2>(); },
    { 3, MyValue.of<NotSubClass>(); }, // this causes a compile error
};
antak
  • 19,481
  • 9
  • 72
  • 80