Declaring a generic restricted type dictionary
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);
}
source to share
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.
source to share
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!
source to share