Мы следуем за trunk=current потоком разработки, branch=release (s) подход. На выпуске клиенту мы переходим соединительная линия и просто сохраняем соединительную линию продвигающейся вперед. Необходимо будет принять решение на том, сколько выпусков Вы готовы поддерживать. Чем больше Вы поддерживаете, тем больше слияния Вы будете делать на исправлениях ошибок. Мы пытаемся сохранить наших клиентов на не больше, чем 2 выпусках позади соединительной линии. (Например, Dev = 1.3, поддерживаемые версии 1.2 и 1.1).
Вероятно, ваш код неверный; вы, вероятно, не рассмотрели все случаи.
Конечно, мы не можем знать, правильный или неправильный какой-либо код, пока у нас не будет спецификации. Итак, начните с написания однострочной спецификации:
" FirstOrValue
принимает последовательность из T, предиката и значения T и возвращает либо первый элемент в последовательности, который соответствует предикат, если он есть, или, если его нет, указанное значение. "
Действительно ли ваша попытка реализует эту спецификацию? Конечно нет! Протестируйте:
int x = FirstOrValue<int>( new[] { -2, 0, 1 }, y=>y*y==y, -1);
возвращает -1. Правильный ответ согласно спецификации - 0. Первый элемент, соответствующий предикату, равен нулю, поэтому он должен быть возвращен.
Правильная реализация спецификации будет выглядеть так:
public static T FirstOrValue<T>(this IEnumerable<T> sequence, Func<T, bool> predicate, T value)
{
if (sequence == null) throw new ArgumentNullException("sequence");
if (predicate == null) throw new ArgumentNullException("predicate");
foreach(T item in sequence)
if (predicate(item)) return item;
return value;
}
Всегда сначала пишите спецификацию, даже если это всего лишь одно предложение.
Первый элемент, соответствующий предикату, равен нулю, поэтому его следует вернуть.Правильная реализация спецификации будет выглядеть так:
public static T FirstOrValue<T>(this IEnumerable<T> sequence, Func<T, bool> predicate, T value)
{
if (sequence == null) throw new ArgumentNullException("sequence");
if (predicate == null) throw new ArgumentNullException("predicate");
foreach(T item in sequence)
if (predicate(item)) return item;
return value;
}
Всегда сначала пишите спецификацию, даже если это всего лишь одно предложение.
Первый элемент, соответствующий предикату, равен нулю, поэтому его следует вернуть.Правильная реализация спецификации будет выглядеть так:
public static T FirstOrValue<T>(this IEnumerable<T> sequence, Func<T, bool> predicate, T value)
{
if (sequence == null) throw new ArgumentNullException("sequence");
if (predicate == null) throw new ArgumentNullException("predicate");
foreach(T item in sequence)
if (predicate(item)) return item;
return value;
}
Всегда сначала пишите спецификацию, даже если это всего лишь одно предложение.
default (T)
вернет null
по умолчанию для ссылочных типов.
Я бы сделал это
public static T FirstOrValue<T>(this IEnumerable<T> source, Func<T, bool> predicate, T value)
{
T first = source.FirstOrDefault(predicate);
return first ?? value;
}
Мне кажется разумным, если вы хотите настроить удобочитаемость вместо использования DefaultIfEmpty.
Вы также можете создать переопределение, которое использует лямбду, если создание значения по умолчанию дорого, создавая только в случае необходимости.
public static T FirstOrValue<T>(this IEnumerable<T> source, Func<T, bool> predicate, Func<T> getValue)
{
T first = source.FirstOrDefault(predicate);
return Equals(first, default(T)) ? getValue() : first;
}