Как избежать цепочки Linq, чтобы вернуть ноль? - PullRequest
2 голосов
/ 19 июня 2010

У меня проблема с кодами контрактов и linq. Мне удалось сузить проблему до следующего примера кода. И теперь я застрял.

public void SomeMethod()
{
    var list = new List<Question>();

    if (list.Take(5) == null) { }
    // resharper hints that condition can never be true

    if (list.ForPerson(12) == null) { }
    // resharper does not hint that condition can never be true
}

public static IQueryable<Question> ForPerson(this IQueryable<Question> source, int personId)
{
    if(source == null) throw new ArgumentNullException();

    return from q in source
           where q.PersonId == personId
           select q;
}

Что не так с моей цепью linq? Почему не резче «жаловаться» при анализе вызова ForPerson?

EDIT : тип возвращаемого значения для метода ForPerson изменен со строки на IQueryable, что я имел в виду (мой плохой)

Ответы [ 2 ]

4 голосов
/ 19 июня 2010

Reshaper правильно, что результат Take или Skip никогда не будет нулевым - если нет элементов, результатом будет IEnumerable<Question>, который не имеет элементов.Я думаю, чтобы сделать то, что вы хотите, вы должны проверить Any.

var query = list.Take(5);
if (!query.Any())
{
    // Code here executes only if there were no items in the list.
}

Но как работает это предупреждение?Решарпер не может знать, что метод никогда не возвращает нуль, только глядя на определение метода, и я предполагаю, что он не выполняет обратный инжиниринг тела метода, чтобы определить, что он никогда не возвращает ноль.Поэтому я предполагаю, что это было специально жестко запрограммированным с правилом, определяющим, что методы .NET Skip и Take не возвращают ноль.

Когда вы пишете свои собственные пользовательские методы, которые может создать Reflectorпредположения о поведении вашего метода из интерфейса, но ваш интерфейс позволяет ему возвращать нуль.Поэтому он не выдает предупреждений.Если бы он проанализировал тело метода, он мог бы увидеть, что ноль невозможен, и мог бы выдать предупреждение.Но анализ кода для определения его возможного поведения - невероятно трудная задача, и я сомневаюсь, что Red Gate готовы потратить деньги на решение этой проблемы, когда они могли бы добавить больше полезных функций в другом месте с гораздо более низкими затратами на разработку.

Чтобы определить, может ли логическое выражение когда-либо возвращать true , называется логическая проблема выполнимости и является NP-трудной проблемой.

Вы хотитеResharper, чтобы определить, может ли тела общего метода когда-либо возвращать null .Это обобщение вышеупомянутой NP-трудной задачи.Вряд ли какой-либо инструмент сможет сделать это правильно в 100% случаев.

0 голосов
/ 19 июня 2010
if(source == null) throw new ArgumentNullException(); 

Это не контрактный код, вместо этого вы имеете в виду:

Contract.Require(source != null);
...