编辑:
从给出的答案中,我已经很清楚我在下面询问的设计应该如何实际实施。考虑到这些建议(并回应礼貌地指出我的示例代码甚至无法编译的评论),我编辑了以下代码以反映普遍共识。鉴于代码,剩下的问题可能不再有意义,但我将其保留为后代。
假设我有一个函数的三个重载,一个 take IEnumerable<T>
,一个takingICollection<T>
和一个taking IList<T>
,如下所示:
public static T GetMiddle<T>(IEnumerable<T> values) {
IList<T> list = values as IList<T>;
if (list != null) return GetMiddle(list);
int count = GetCount<T>(values);
T middle = default(T);
int index = 0;
foreach (T value in values) {
if (index++ >= count / 2) {
middle = value;
break;
}
}
return middle;
}
private static T GetMiddle<T>(IList<T> values) {
int middleIndex = values.Count / 2;
return values[middleIndex];
}
private static int GetCount<T>(IEnumerable<T> values) {
// if values is actually an ICollection<T> (e.g., List<T>),
// we can get the count quite cheaply
ICollection<T> genericCollection = values as ICollection<T>;
if (genericCollection != null) return genericCollection.Count;
// same for ICollection (e.g., Queue<T>, Stack<T>)
ICollection collection = values as ICollection;
if (collection != null) return collection.Count;
// otherwise, we've got to count values ourselves
int count = 0;
foreach (T value in values) count++;
return count;
}
这里的想法是,如果我有一个IList<T>
,那会使我的工作变得最简单;另一方面,我仍然可以使用 anICollection<T>
甚至 an来完成这项工作IEnumerable<T>
;这些接口的实现效率不高。
我不确定这是否可行(如果运行时能够根据传递的参数选择重载),但我已经对其进行了测试,并且似乎可以。
我的问题是:这种方法有没有我没有想到的问题?或者,这实际上是一个好方法吗,但是有更好的方法来实现它(也许通过尝试将values
参数转换为IList<T>
第一个并在转换有效时运行更有效的重载)?我只是想知道别人的想法。