繁体   English   中英

C# 等效于 Java 列表<? extends Class>

[英]C # equivalent of Java List<? extends Class>

我有一个泛型类的基本结构

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

public class Child : Parent<Child>
{
}

我想要一个列表,以便可以将 Child 对象放在那里

List<Parent> parents = new List<Parent>();

在 Java 中,我只能写List<? extends Parent> List<? extends Parent>和所有 Parent 的子类都可以轻松添加到列表中。 在 C# 中是否有其他选择?

您不能做与 Java 相同的事情,因为在 Java 中,泛型使用类型擦除和中断差异。 本质上,您的 Java 代码将所有内容都转换为List<object> ,并希望做到最好。 List<?>优于List<Object>的唯一原因是在 Java 中并非所有东西都是Object - 在 C# 中,您可以在List<object>放入一个整数就好了。 请注意,如果您负担得起, List<int>性能将比List<object>好得多 - 这是泛型最初添加到 C# 的重要原因之一。

C# 比这更严格一些。 你不能做任何像new List<Parent<T>>()这样会允许任何类型的Parent<T>事情。 如果您有更有限的要求,您可以改用变体接口,但由于显而易见的原因,这不适用于List<T>

您唯一真正的选择是使基类成为非泛型。 无论如何,您的列表中的用户无法提前了解T任何信息,因此返回或接受TParent接口的任何部分如果不进行任何转换都将毫无用处(Java 为您进行了转换,但它仍在转换 - Java 和 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>();

当您需要获取例如所有Child项时,您可以这样做

var children = list.OfType<Child>();

为了完整起见,您可以使用 C# 的dynamic获得与 Java 类似的行为。 但我什至不打算展示任何示例 - dynamic是一个有用的工具,但主要用于更动态的类型问题。 对于像这样简单的事情来说这是矫枉过正的,并且将编译时问题换成了运行时问题。

一般来说,如果你曾经直接使用Parent<T> ,它应该是一个泛型方法——例如一个扩展方法,它具有所有Parent<T>的一些通用功能。 您不能实例化一个不具有当时在 C# 中已知的所有类型参数的泛型类型。

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

当你说, public class Child : Parent<Child>它继承Parent<Child>而不是Parent<T>

所以List<Parent<Child>> list; 将只接受 Child 类的对象,而不接受 Parent 的任何其他子类。

您仍然可以在如下界面的帮助下实现您需要的功能:在这里工作小提琴

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM