C#相当于Java列表<;?扩展类>;

C#相当于Java列表<;?扩展类>;,c#,generics,generic-collections,C#,Generics,Generic Collections,我有泛型类的基本结构 public class Parent<T> where T : Parent<T> { Action<T> Notify; } public class Child : Parent<Child> { } 公共类父级,其中T:Parent { 行动通知; } 公共类子级:父级 { } 我想要一个列表,这样子对象就可以放在那里了 List parents=newlist() 在java中,我只能编写List,您不能

我有泛型类的基本结构

public class Parent<T> where T : Parent<T>
{
   Action<T> Notify;
}

public class Child : Parent<Child>
{
}
公共类父级,其中T:Parent
{
行动通知;
}
公共类子级:父级
{
}
我想要一个列表,这样子对象就可以放在那里了

List parents=newlist()


在java中,我只能编写
List,您不能做与java相同的事情,因为在java中,泛型使用类型擦除和中断方差。本质上,您的Java代码将所有内容都转换为
列表
,并希望做到最好。
List
优于
List
的唯一原因是,在Java中并非所有东西都是
对象
——在C#中,可以在
列表
中放入整数。记住,
列表
的性能比
列表
好得多,如果你负担得起的话——这就是泛型最初被添加到C#的一个重要原因

C#比那要严格一点。您不能执行任何类似于
newlist()
的操作来允许任何类型的
父级
。如果您有更有限的需求,您可以改用变体接口,但由于明显的原因,
List
无法使用

您唯一的实际选择是使基类非泛型。您列表的用户无论如何都不能事先知道有关
t
的任何信息,因此
Parent
界面中返回或获取
t
的任何部分在不强制转换的情况下都不会有用(Java为您进行转换,但它仍然在转换——Java和C#的泛型都不能满足您的需要)

为了完整性起见,您可以通过C#的
动态
获得与Java类似的行为。但我甚至不打算展示任何示例-
动态
是一个有用的工具,但主要用于更多的动态类型问题。对于像这样简单的问题,它有点过头了,用编译时问题来交换运行时问题

一般来说,如果您曾经直接使用
Parent
,那么它应该在泛型方法中—例如,一个扩展方法,它对所有
父类都有一些公共功能。您不能实例化一个泛型类型,因为它没有C#中当时已知的所有类型参数。

声明
List Parent;
不编译,因为它需要类型参数

当你说,
公共类Child:Parent
它继承了
Parent
而不是
Parent

所以
List;
只接受子类的对象,而不接受父类的任何其他子类的对象

您仍然可以通过以下界面实现所需的功能:

公共类程序
{
公共静态void Main()
{
List parentList=新列表();
parentList.Add(newchild1());
parentList.Add(newchild2());
}
}
公共类父类
{ }
公共接口IParent
{ }
公共类Child1:父级,IParent
{ }
公共类Child2:父级,IParent
{ }

不,不是。我有编译错误
Generic.List需要'1'类型的参数
(它是本地化的,但类似于此)由于类型参数,您必须声明它
List
。该类型约束很难闻。您这样做是因为它看起来与Java中的类似,还是因为没有它您无法在C中完成所需的工作?为什么基类是泛型的?来自同一个类。类型约束使这不可能,因为se基类最终是不同的。C#具体化了泛型,而不是类型擦除。
public abstract class Parent
{
  // The common methods
  public abstract int Id { get; }
}

public abstract class Parent<TChild> : Parent, IEnumerable<TChild>
{
  // The methods that are TChild-specific - if you don't need any of those, just drop
  // this class, the non-generic one will work fine
  private List<TChild> children;
  public void Add(TChild child) => ...
  public TChild this[int index] => ...
}

public class Child : Parent<TChild>
{
  ...
}
var list = new List<Parent>();
var children = list.OfType<Child>();
public class Program
{
    public static void Main()
    {
        List<Parent<IParent>> parentList = new List<Parent<IParent>>();

        parentList.Add(new Child1());
        parentList.Add(new Child2());       
    }
}
public class Parent<T> 
{ }
public interface IParent
{ }

public class Child1 : Parent<IParent>, IParent
{ }

public class Child2 : Parent<IParent>, IParent
{ }