我有一个方法,我想在我的解决方案中采取所有类似列表的对象。在.NET 4.5之前,这很简单:
public static T Method<T>(IList<T> list)
{
// elided
}
但是,.NET 4.5引入了IReadOnlyList<T>
,这种方法也适用于。{/ p>
我不能只改变签名以取IReadOnlyList<T>
,因为有些地方我会将这种方法应用于IList<T>
专门输入的内容。
该算法无法在IEnumerable<T>
上运行,并且过于频繁地使用(并且对象太大)无法在每次调用时使用IEnumerable<T>
并创建新的List<T>
。 / p>
我尝试过添加一个重载:
public static T Method<T>(IReadOnlyList<T> list)
{
// elided
}
...但是这不会编译实现两个接口(T[]
,List<T>
和许多其他类型)的任何东西,因为编译器无法确定使用哪种方法(特别是因为他们拥有相同的身体而烦人,所以没关系)。
我不想添加带Method
和T[]
的{{1}}的重载,以及实现这两个接口的所有其他类型的重载。
我该如何做到这一点?
答案 0 :(得分:4)
这可能是实际检查运行时类型有用的场合之一:
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
的单独实现,因为您没有可以利用的通用接口,但至少可以避免不明确的呼叫问题。< / p>
答案 1 :(得分:2)
您最好的选择是进行全局搜索并将IList
替换为IReadOnlyList
。如果没有编译器错误那么你应该没问题。
如果您使用的是IList.Add
,那么您应该只收到编译器错误 - 无论如何这都是蛮干的,因为数组不支持Add
。
答案 2 :(得分:0)
您可以更改Method调用的代码吗? 如果您创建这样的方法怎么办:
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();
答案 3 :(得分:-1)
也许你最好的解决方案是研究为什么你的算法不能在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>
接口,而不是复制成员。这并不能帮助你。