簡體   English   中英

使用IList進行C#重載解析 <T> 和IReadOnlyList <T>

[英]C# overload resolution with IList<T> and IReadOnlyList<T>

我有一個方法,我想在我的解決方案中采取所有類似列表的對象。 在.NET 4.5之前,這很簡單:

public static T Method<T>(IList<T> list)
{
    // elided
}

但是,.NET 4.5引入了IReadOnlyList<T> ,該方法也應該適用於此。

我不能只改變簽名來獲取IReadOnlyList<T> ,因為有些地方我將這個方法應用於特定類型的IList<T>

該算法不能在IEnumerable<T>上運行,並且它太頻繁地使用(並且對象太大)來獲取IEnumerable<T>並在每次調用時創建一個新的List<T>

我試過添加一個重載:

public static T Method<T>(IReadOnlyList<T> list)
{
    // elided
}

...但是這不能編譯實現兩個接口( T[]List<T>和許多其他類型)的任何東西,因為編譯器無法確定使用哪種方法(特別煩人,因為它們具有相同的身體,所以沒關系)。

我不想添加帶有T[]List<T>Method重載,以及實現這兩個接口的所有其他類型。

我該怎么做到這一點?

這可能是實際檢查運行時類型有用的場合之一:

public static T Method<T>(IEnumerable<T> source)
{
    if (source is IList<T> list)
        return Method(list);

    if (source is IReadOnlyList<T> readOnly)
        return Method(readOnly);

    return Method(source.ToList() as IList<T>);
}

private static T Method<T>(IReadOnlyList<T> list) { ... }
private static T Method<T>(IList<T> list) { ... }

您仍然需要復制代碼,因為您需要為IListIReadOnlyList單獨實現,因為沒有可以利用的通用接口,但您至少可以避免出現模糊的調用問題。

您可能最好的選擇是進行全局搜索並將IList替換為IReadOnlyList 如果沒有編譯器錯誤,那么你應該沒問題。

如果您使用的是IList.Add ,那么您應該只收到編譯器錯誤 - 無論如何這都是IList.Add ,因為數組不支持Add

你能改變方法調用的代碼嗎? 如果您創建這樣的方法怎么辦:

    public static T1 Method<T1, T2>(T2 list) where T2 : IList<T1>, IReadOnlyList<T1>
    {
        return default(T1);
    }

在這種情況下,調用如下所示:

List<string> listA = new List<String>();
ReadOnlyCollection<string> listB = listA.AsReadOnly();

string outVar1 = Method<string, List<string>>(listA);
string outVar2 = Method<string, ReadOnlyCollection<string>>(listB);

以這種方式為IList和IReadOnlyList創建兩個擴展方法的另一種方法:

    public static T Test<T>(this IList<T> source)
    {
        return default(T);
    }

    public static T Test<T>(this IReadOnlyList<T> source)
    {
        return default(T);
    }

並稱他們為:

    string outVar1 = (listA as IReadOnlyList<string>).Test();
    string outVar2 = (listB as IList<string>).Test();

也許你最好的解決方案是調查為什么你的算法無法在IEnumerable上運行並改變它。 您是否正在使用IList<T>IReadOnlyList<T>特定成員,您可以使用IEnumerable<T>可用的成員替換它們? 例如:

// instead of
int c = list.Count;

// use
int c = list.Count();

編輯:忽略下面的廢話。 我要離開它,以便評論繼續有意義。

您不應該在任何類中實現IList<T>IReadOnlyList<T> IList規范中唯一的附加成員是寫入列表。 如果您的列表是只讀的,則不需要這樣做。 我認為您需要更改任何實現兩者的類,以便在使用它們時可以選擇正確的方法。

但是,由於IReadOnlyList<T>所有成員都包含在IList<T> (以及從IReadOnlyCollection<T>派生的那些成員),我想知道.Net中的IList<T>是否應該實際更改,以便它繼承IReadOnlyList<T>界面而不是復制成員。 這並不是說現在有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM