簡體   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