Declaring a generic restricted type dictionary

I need to declare Dictionary

with Type

as key and instance value as.

I need to constrain the key type to a specific class hierarchy.

For a Java card, I can do something like:

Map<Class<? extends MySuperClass>, ? extends MySuperClass>

      

How can I achieve this in C #?

+3


source to share


4 answers


Do not expose Dictionary

directly, this way you can manually control when to add



public void AddToDictionary(Type key, object value)
{
    if(!key.IsAssignableFrom(typeof(SomeBaseClass))
        throw new ArgumentException("Must be an inherited from SomeBaseClass type");
    dictionary.Add(key, value);
}

      

+2


source


I think Sinatr's approach of exporting the add method to the dictionary instead of the dictionary itself is a very good idea. The only drawback is that you don't get any compile-time safety; if some code added an object of the wrong type that you would not have known until runtime.

The use of generics, however, can be configured in such a way that the added objects are reliable:



public void AddToDictionary<T>(T value) where T: MySuperClass
{
    dict.Add(typeof(T), value);
}

      

It is no longer possible to write a program that adds objects of the wrong type and still compiles.

+2


source


You can use typeof

to get the type of a class so that something like:

Map<System.Type, object>

      

I'm not sure how you would apply extensions for this. This should probably happen as a test before being added to the map.

0


source


You can:

public class MyType<TBase>
{
    private Type Value;

    protected MyType()
    {
    }

    public static implicit operator Type(MyType<TBase> type)
    {
        return type.Value;
    }

    public static implicit operator MyType<TBase>(Type type)
    {
        if (type == null)
        {
            throw new ArgumentNullException();
        }

        if (!typeof(TBase).IsAssignableFrom(type))
        {
            throw new ArgumentException();
        }

        return new MyType<TBase> { Value = type };
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
        {
            return false;
        }

        var type = obj as MyType<TBase>;

        return type != null && Value.Equals(type.Value);
    }

    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }

    public override string ToString()
    {
        return Value.ToString();
    }
}

      

and then:

Dictionary<MyType<MySuperClass>, MySuperClass> dict = new Dictionary<MyType<MySuperClass>, MySuperClass>();
dict.Add(typeof(MyClass1), new MyClass1());

      

MyType

has implicit from / to operators Type

, so it's pretty easy to use. You just cast Type

on MyType

(or a MyType

on Type

) and it just works. Example TryGetValue()

:

MySuperClass ms;

if (!dict.TryGetValue(typeof(MyClass1), out ms))
{
    throw new Exception();
}

      

Note that the checks are done at runtime!

0


source







All Articles