2010-06-19 6 views
2

J'ai un problème avec les contrats de code et linq. J'ai réussi à limiter le problème à l'exemple de code suivant. Et maintenant je suis coincé.Comment éviter Linq chaining pour retourner null?

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; 
} 

Quel est le problème avec ma chaîne linq? Pourquoi ne pas se plaindre lors de l'analyse de l'appel ForPerson?

EDIT: le type de retour pour la méthode ForPerson a changé de chaîne en IQueryable, ce que je voulais dire. (ma mauvaise)

Répondre

4

Reshaper est correct que le résultat d'un Take ou Skip n'est jamais nul - s'il n'y a aucun élément le résultat est un IEnumerable<Question> qui n'a aucun élément. Je pense que pour faire ce que vous voulez, vous devriez vérifier Any.

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

Mais comment cet avertissement fonctionne-t-il? Resharper ne peut pas savoir que la méthode ne renvoie jamais null en regardant uniquement la définition de la méthode, et je suppose qu'elle n'inverse pas le corps de la méthode pour déterminer qu'elle ne retourne jamais null. Je suppose donc qu'il a été spécialement codé en dur avec une règle spécifiant que les méthodes .NET Skip and Take ne renvoient pas de null. Lorsque vous écrivez vos propres méthodes personnalisées, Reflector peut émettre des hypothèses sur le comportement de votre méthode à partir de l'interface, mais votre interface lui permet de renvoyer une valeur null. Par conséquent, il n'émet aucun avertissement. S'il analysait le corps de la méthode, il pouvait voir que null était impossible et serait capable d'émettre un avertissement. Mais analyser le code pour déterminer son comportement possible est une tâche incroyablement difficile et je doute que Red Gate soit prêt à dépenser de l'argent pour résoudre ce problème quand ils pourraient ajouter des fonctionnalités plus utiles ailleurs avec un coût de développement beaucoup plus bas.

Pour déterminer si une expression booléenne ne peut jamais revenir vrai est appelé Boolean satisfiability problem et est un problème NP-dur.

Vous voulez ReSharper déterminer si corps de méthode générale peut jamais revenir nulle. Ceci est une généralisation du problème NP-difficile mentionné ci-dessus. Il est peu probable qu'un outil soit capable de le faire correctement dans 100% des cas.

+0

Merci pour votre réponse rapide. Le type de retour aurait dû être IQueryable . J'ai changé cela dans ma question. Le problème est que les resharpers ne se plaignent pas. Ca devrait parce que ForPeson ne retournera jamais null. – Florian

+0

Merci pour ça. +1 –

+1

En fait, je crois comprendre que ReSharper a inversé les diverses méthodes, et ensuite les codes durs les valeurs déterminées par l'ingénierie inverse. Le résultat est qu'il arrive parfois à de fausses conclusions, comme cela 'XmlReader.Create' peut retourner null. Il y a un cas de bord très obscur où il pourrait. –

0
if(source == null) throw new ArgumentNullException(); 

Ce n'est pas la voie du contrat de code, voulez-vous dire à la place:

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

Non, ce n'est pas ce que je voulais dire. Vous pouvez remplacer 'if (list.ForPerson (12) == null)' par quelque chose comme 'Contract.Requires (list.ForPerson (12)! = Null)' et vous avez le même problème. Ce qui est effectivement le problème que je rencontre. Puisque plus de gens utilisent Resharper que les Contrats de Code, j'ai pensé à poser la question dans le contexte de Resharper ... – Florian

+1

Je vois, la question est marquée par des contrats de code et non étiquetée resharper donc j'étais confus. Anyhoo - ce scénario devrait être supporté par les contrats de code. –

Questions connexes