Контракты кода: требуется, чтобы IEnumerable был непустым - PullRequest
2 голосов
/ 22 декабря 2010

У меня есть следующий код:

public static IEnumerable<long> GetAllCombinations(IEnumerable<long> elements)
{
    Contract.Requires(elements != null);
    return GetAllCombinations(elements.ToList(), 0);
}

Статический анализ теперь говорит мне добавить еще одно предварительное условие:

CodeContracts: Предлагаемое предварительное условие: Contract.Requires (максимум> = 0)

Я не понимаю предложение, потому что

a) Если я уже проверяю, что elements не равно NULL, зачем мне проверять, равно ли его количествобольше или равно нулю?Я имею в виду, что передача ненулевого значения уже означает, что оно содержит как минимум нулевые элементы?

б) Как я должен проверить количество (или максимум, как предлагается) IEnumerable?Единственный способ, которым я вижу, - это присвоить elements.ToList() дополнительной переменной и проверить эту переменную.Но что, если я никогда не захочу составить список из IEnumerable?

Смущает меня.

EDIT:

Iзнаю все методы расширения для IEnumerable<T> и хорошо знаю .Any(), .Count() и т. д.

Что меня удивляет, так это сообщение от статического анализатора.Кто-нибудь может объяснить, почему в нем говорится Contract.Requires(maximum >= 0)?

Означает ли это, что я думаю (проверка количества элементов> = 0)?

И, как уже упоминалось в комментарии, почему статический анализатор все еще не удовлетворен Contract.Requires(elements.Any());?

Ответы [ 3 ]

1 голос
/ 22 декабря 2010

Я не уверен, почему статический анализ предлагает проверить счет коллекции.Если передается пустая коллекция, код, который ее оценивает, не будет выполнен (т.е. оператор foreach), что должно быть в порядке. Возможно, это как-то связано с Count коллекции, являющейся типом со знаком?Возможно, вы захотите попытаться удовлетворить статический анализатор чем-то вроде Contracts.Assume(elements.Any()) или оператором, в котором говорится, что число неотрицательно.

Чтобы ответить на ваш второй вопрос, существует множество способов определить, является ли IEnumerable<> структура не пуста.Чтобы перечислить несколько, включенных пространством имен System.Linq:

  • elements.Any() // Проверяет наличие хотя бы одного элемента, O (1).
  • elements.Count() // Подсчитывает все элементы, O (n)
  • elements.Single() // Вызывает исключение, если существует более одного элемента, O (1).
  • elements.First() // Возвращаетпервый элемент, или вызывает исключение, если оно пустое, O (1).

Следующие два варианта эквивалентны elements.Any (), где T - тип элемента в контейнере:

  • elements.SingleOrDefault() != default(T)
  • elements.FirstOrDefault() != default(T)
0 голосов
/ 22 декабря 2010

Я имею в виду, передавая ненулевое значение уже означает, что он содержит по крайней мере ноль элементов?

Нет. Некоторые API-интерфейсы, возвращающие IEnumerable, все время возвращают что-то автоматически - просто пустое.

Как мне проверить счет? (или максимум, как предполагается) IEnumerable?

Это реальная проблема на самом деле. Enumerable не имеет API для этого.

0 голосов
/ 22 декабря 2010

elements.Count<long>() даст вам счет за IEnumerable<long>. Вы все еще хотите проверить счетчик, поскольку некоторые методы генерируют исключение в пустом IEnumerable (например, Single <>).

...