代码之家  ›  专栏  ›  技术社区  ›  edosoft

将基对象用作泛型函数中的参数

  •  1
  • edosoft  · 技术社区  · 16 年前

    我正在尝试使用泛型实现一个助手方法(c/3.5) 我有一个很好的类结构,有这样的基类:

    public class SomeNiceObject : ObjectBase
    {
      public string Field1{ get; set; }
    }
    
    public class CollectionBase<ObjectBase>()
    {
      public bool ReadAllFromDatabase();
    }
    
    public class SomeNiceObjectCollection : CollectionBase<SomeNiceObject>
    {
    
    }
    

    我希望使用这样的通用方法检索集合:

        public class DAL
        {
    
         public SomeNiceObjectCollection Read()
         {
          return ReadFromDB<SomeNiceObjectCollection>();
         }
    
         T ReadFromDB<T>() where T : CollectionBase<ObjectBase>, new()
         {
          T col = new T();
          col.ReadAllFromDatabase();
          return col;          
         }
       }
    

    这不是建立,用

    Error   66  The type 'SomeNiceObjectCollection' cannot be used as type parameter 'T' in the generic type or method 'ReadFromDB<T>'.   There is no implicit reference conversion from 'SomeNiceObjectCollection' to 'CollectionBase<ObjectBase>'.
    

    SomeNiceObjectCollection对象是CollectionBase,确切地说是CollectionBase。那么我如何才能让这个工作呢?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Martin Harris    16 年前

    C不支持列表类型之间的强制转换(协方差)。

    支持此模式的最佳选择是为readAllFromDatabase方法引入一个接口,这样您就不需要依赖通用集合:

    public class SomeNiceObject : ObjectBase
    {
      public string Field1{ get; set; }
    }
    
    public interface IFromDatabase
    {
      bool ReadAllFromDatabase();
    }
    
    public class CollectionBase<ObjectBase>() : IFromDatabase
    {
      public bool ReadAllFromDatabase();
    }
    
    public class SomeNiceObjectCollection : CollectionBase<SomeNiceObject>
    {
    
    }
    
    public class DAL
    {
    
     public SomeNiceObjectCollection Read()
     {
      return ReadFromDB<SomeNiceObjectCollection>();
     }
    
     T ReadFromDB<T>() where T : IFromDatabase, new()
     {
      T col = new T();
      col.ReadAllFromDatabase();
      return col;          
     }
    }
    
        2
  •  2
  •   Lasse V. Karlsen    16 年前

    在C 3.0中,这是不可能的,但是在C和带有协方差和反方差的.NET 4.0中,这是可能的。

    考虑一下,您将获取一个包含派生对象的集合,并尝试临时将其视为基对象的集合。如果允许这样做,您可以将基对象插入到列表中,而不是派生对象。

    这里有一个例子:

    List<String> l = new List<String>();
    List<Object> o = l;
    l.Add(10); // 10 will be boxed to an Object, but it is not a String!