C# 在泛型函数中将基础对象用作参数

C# 在泛型函数中将基础对象用作参数,c#,generics,base-class,C#,Generics,Base Class,我正在尝试使用泛型C/3.5实现一个助手方法 我有一个很好的类结构,基类如下: public class SomeNiceObject : ObjectBase { public string Field1{ get; set; } } public class CollectionBase<ObjectBase>() { public bool ReadAllFromDatabase(); } public class SomeNiceObjectCollection

我正在尝试使用泛型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。那么我如何才能让它工作呢?

在C3.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!

在C3.0中这是不可能的,但是在C和.NET4.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!

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

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

Excellence.CollectionBase allready实现了我需要的接口,因此我更改了ReadFromDB。谢谢Excellence.CollectionBase allready实现了我需要的接口,因此我更改了ReadFromDB。谢谢