通用类和接口的非通用版本

时间:2009-06-17 08:56:15

标签: c# generics covariance

我经常发现自己处于创建通用接口或类的情况,然后希望以非通用方式使用此类或接口的不同版本。例如,我可能有这样的界面:

interface ICanCreate<T>
{
    T NewObject();
}

允许类成为该类型的工厂。然后我想用一般工厂类注册这些,所以我尝试写这样的东西:

public class Factory
{
    private Dictionary<Type, ICanCreate> mappings; // what do I put here????

    public void RegisterCreator<T>(ICanCreate<T> creator)
    {            
    }

    public T Create<T>()
    {            
    }
}

在字典中,我使用哪种类型的价值?我不知道我是否缺少某种设计原则,我知道这与co(ntra?)方差有很大关系。任何帮助或想法将不胜感激。

2 个答案:

答案 0 :(得分:11)

你要么只需要在你的字典声明中使用object(它都是私有的,可以验证你永远不会把错误的东西放在那里)或宣布ICanCreate扩展的非通用ICanCreate<T>接口。

基本上你想要一个无法在C#中表达的类型关系 - 无论何时发生这种情况,你最终会得到一个稍微不愉快的解决方案,但看起来你可以在这里孤立丑陋(即将它保持在单一类别中) )。

答案 1 :(得分:3)

有趣的是,这是一个在C#4.0中解决的问题:

public interface ICanCreate<out T> // covariant
{
    T NewObject();
}

public class Factory
{
    private Dictionary<Type, ICanCreate<object>> mappings = new Dictionary<Type, ICanCreate<object>>();

    public void RegisterCreator<T>(ICanCreate<T> creator) where T:class
    {            
      mappings[typeof(T)] = creator;
    }

    public T Create<T>()
    {            
      ICanCreate<object> creator = mappings[typeof(T)];
      return (T) creator.NewObject(); // I do not think you can get rid of this cast
    }
}