[英]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) { ... }
您仍然需要復制代碼,因為您需要為IList
和IReadOnlyList
單獨實現,因為沒有可以利用的通用接口,但您至少可以避免出現模糊的調用問題。
您可能最好的選擇是進行全局搜索並將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.