[英]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.