EDIT
Из приведенных ответов мне стало ясно, как на самом деле должен быть реализован дизайн, о котором я спрашиваю ниже. Имея в виду эти предложения (и в ответ на комментарий, вежливо указывающий на то, что мой пример кода даже не компилируется ), я отредактировал следующий код, чтобы отразить то, как выглядит общее согласие. Вопрос, который остается, может больше не иметь смысла в свете кода, но я оставляю его так же, как и для потомков.
Предположим, у меня есть три перегрузки функции: одна принимает IEnumerable<T>
, одна - ICollection<T>
, а другая - 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>
, это облегчает мою работу; с другой стороны, я все еще могу делать эту работу с ICollection<T>
или даже IEnumerable<T>
; реализация для этих интерфейсов не так эффективна.
Я не был уверен, сработает ли это вообще (если среда выполнения сможет выбирать перегрузку на основе переданного параметра), но я проверил это, и, похоже,
Мой вопрос: есть ли проблема с этим подходом, о котором я не задумывался? С другой стороны, действительно ли это хороший подход, но есть лучший способ выполнить его (возможно, попытавшись привести аргумент values
до значения IList<T>
и запустить более эффективную перегрузку, если приведение работает)? Мне просто интересно узнать мысли других.