Из ответов, это было сделано достаточно ясно для меня, как на самом деле должен быть реализован проект, я спрашиваю о ниже. С учетом этих предложений (и в ответ на комментарий, вежливо указывающий, что в моем примере кода нет даже компиляции), я отредактировал следующий код, чтобы отразить общее мнение. Вопрос, который остается, может уже не иметь смысла в свете кода, но я оставляю его так же, как и для потомков.
Предположим, у меня есть три перегруженные функции, один принимая 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>
и запустить более эффективную перегрузку, если бросок работает)? Мне просто интересно узнать мысли других.
«GetMiddle for» IEnumerable и «ICollection» как «не собираются компилировать, поскольку« не все пути возвращают значение ». GetMiddle 'List собирается сбой, если передан список «нулевой элемент» с исключением исключения диапазона индекса. best, –
BillW
@BillW: Да, я понимаю это, хотя справедливо, что вы его воспитываете. Эти примеры кода были просто для освещения моего вопроса. –
@ Dan Извините, что я «придирчивый, придирчивый»: это новая область исследований для меня, и я с сожалением могу сказать, что пока неясно, просто добавив что-то вроде возврата по умолчанию (T), позаботится обо всех возможных случаях и непонятно, что такое «лучшая практика» с точки зрения обработки исключений в таких методах утилиты: но, возможно, мне стоит просто задать вопрос о StackOverFlow :) best, – BillW