用有界类型声明通用字典

时间:2015-06-30 14:46:21

标签: c# .net generics

我需要声明DictionaryType为键,实例为值。

我需要将键类型限制为某个类层次结构。

对于Java Map,我可以这样做:

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

如何在C#中实现这一目标?

4 个答案:

答案 0 :(得分:2)

不要直接公开Dictionary,这样您就可以手动控制何时添加

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);
}

答案 1 :(得分:2)

我认为Sinatr公开一种添加到字典而不是字典本身的方法的方法是一个非常好的主意。唯一的缺点是你没有编译时安全;如果某些代码添加了错误类型的对象,那么直到运行时才能找到它。

然而,使用泛型,我们可以调整方法,以便添加对象是万无一失的:

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

现在不可能编写一个程序来添加错误类型的对象并仍然编译。

答案 2 :(得分:0)

您可以使用typeof来获取类的类型,例如:

Map<System.Type, object>

我不确定你将如何强制执行此扩展。这应该在添加到地图之前作为测试发生。

答案 3 :(得分:0)

你可以:

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();
    }
}

然后:

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

MyType具有来自/到Type的隐式运算符,因此使用起来非常简单。您只需将Type投射到MyType(或MyType投放到Type),它就可以了。 TryGetValue()的示例:

MySuperClass ms;

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

请注意,检查是在运行时完成的!