При работе с перечислением, содержащим none, один или несколько элемента, цикл foreach
упрощает их перебор, а LINQ Select
облегчает проецирование элементов из перечисления.
foreach (var attr in p.GetCustomAttributes().OfType<A>()) ...
При работе с перечислением, содержащим нет или только один элемента, все немного сложнее.Вы можете использовать тот же цикл foreach
, но это не гарантирует, что присутствует только один из элементов, и он может выполняться более одного раза.
Вы можете добавить .Take(1)
, чтобы дать понять, что вытолько хотите до одного и убедитесь, что цикл выполняется только один раз.Но это не приведет к исключению, если их больше одного.
foreach (var attr in ...().Take(1)) ...
Вы можете добавить проверку заранее, чтобы убедиться, что есть только один, или, возможно, новый контракт кода для проверки, ноэто довольно грязно:
Contract.Requires(p..GetCustomAttributes().OfType<A>().Count() < 2);
foreach (var attr in p.GetCustomAttributes().OfType<A>()) ...
Вы даже можете создать новый метод расширения .ZeroOrOne<T>()
, который возвращает первый элемент в перечислении, а затем выдает исключение, если вы запрашиваете больше.
foreach (var attr in ...().ZeroOrOne()) ...
Или вы можете избавиться от цикла, использовать .SingleOrDefault()
, а затем проверить на нулевое значение, которое, безусловно, является самым ясным из всех с точки зрения намерений и гарантирует, что цикл выполняется ноль или один раз, но опять же, это больше кода, это меньше 'декларативный «и он не« составной »:
var attr = p.GetCustomAttributes().OfType<A>().SingleOrDefault();
if (attr != null)
{
...
Итак, на вопрос: что из перечисленного (или других предложений) предпочитают люди и почему? Большинство программистов, привыкших к процедурному коду, естественно предпочитают оператор if
, но для тех из вас, кто занимается функциональным программированием, у вас есть лучший подход?
В некоторых других языках есть чистые методы длясправиться с этим, например, шаблоны массивов F # могут соответствовать нулю, одному или нескольким, или не работать.Существует ли случай для конструкции forone
на языке C #, который был бы эквивалентен проверке, что в перечислении есть ноль или единица, и затем его выполнению?
[Конкретный пример здесь - получениенастраиваемые атрибуты, где атрибут помечен как недопустимый, но вопрос в целом касается обработки случая ноль / один.]