LINQ SelectMany et Où la méthode d'extension en ignorant les valeurs null

J'ai l'exemple ci-dessous de code, et je suis intéressé de savoir comment je peux faire tout ce nettoyant, éventuellement par le biais d'une meilleure utilisation de SelectMany(). À ce stade, le QuestionList propriété ne sera pas nulle. Tout ce que je veux est une liste de answerRows qui ne sont pas nulles, mais Questions peut parfois être null.

IEnumerable<IQuestion> questions = survey.QuestionList
                    .Where(q => q.Questions != null)
                    .SelectMany(q => q.Questions);

if(questions == null)
return null;

IEnumerable<IAnswerRow> answerRows = questions
                    .Where(q => q.AnswerRows != null)
                    .SelectMany(q => q.AnswerRows);

if(answerRows == null)
return null;

Mise à JOUR:
Changé mon code légèrement parce que mon exemple n'était pas assez claire avec l'utilisation de var

La question était plus pour m'aider à en savoir plus sur l'utilisation de LINQ.

Mise à JOUR 2:

J'ai été intéressé par Jon commentaire à propos de Enumerable.SelectMany et Nulle..
j'ai donc voulu essayer mon exemple avec des fausses données plus facile de voir où est l'erreur, veuillez voir ci-dessous, spécifiquement la façon dont j'utilise SelectMany() sur le résultat d'un SelectMany(), son plus clair pour moi maintenant que le problème était d'avoir à vous assurer que vous n'utilisez pas SelectMany() sur une référence null, évident quand j'ai lu le NullReferenceException nom 🙁 et, enfin, à mettre les choses ensemble.

Aussi en faisant cela, j'ai réalisé que l'utilisation de try { } catch() { } dans cet exemple, est inutile, et comme d'habitude, Jon Skeet a la réponse 🙂 l'exécution différée..

donc, si vous voulez voir l'exception de la ligne 2, commentaire de la ligne de bits à 1 :P, désolé, je ne pouvais pas comprendre comment arrêter cette erreur sans avoir à ré-écrire le code d'exemple.

using System;
using System.Collections.Generic;
using System.Linq;
namespace SelectManyExample
{
class Program
{
static void Main(string[] args)
{
var questionGroupList1 = new List<QuestionGroup>() {
new QuestionGroup() {
Questions = new List<Question>() {
new Question() {
AnswerRows = new List<AnswerRow>() {
new AnswerRow(),
new AnswerRow()
}
},
//empty question, causes cascading SelectMany to throw a NullReferenceException
null,
new Question() {
AnswerRows = new List<AnswerRow>() {
new AnswerRow() {
Answers = new List<Answer>() {
new Answer(),
new Answer()
}
}
}
}
}
}
};
var questionGroupList2 = new List<QuestionGroup>() {
null,
new QuestionGroup()
};
IEnumerable<AnswerRow> answerRows1 = null;
IEnumerable<AnswerRow> answerRows2 = null;
try
{
answerRows1 = questionGroupList1
.SelectMany(q => q.Questions)
.SelectMany(q => q.AnswerRows);
}
catch(Exception e) {
Console.WriteLine("row 1 error = " + e.Message);
}
try
{
answerRows2 = questionGroupList2
.SelectMany(q => q.Questions)
.SelectMany(q => q.AnswerRows);
}
catch (Exception e)
{
Console.WriteLine("row 2 error = " + e.Message);
}
Console.WriteLine("row 1: " + answerRows1.Count());
Console.WriteLine("row 2: " + answerRows2.Count());
Console.ReadLine();
}
}
public class QuestionGroup {
public IEnumerable<Question> Questions { get; set; }
}
public class Question {
public IEnumerable<AnswerRow> AnswerRows { get; set; }
}
public class AnswerRow {
public IEnumerable<Answer> Answers { get; set; }
}
public class Answer {
public string Name { get; set; }
}
}
Pourquoi pensez-vous que vos collections de jamais être nulle?
questions et answerRows ne peut jamais être null. Et dans une saine conception, q.Questions et q.AnswerRows probablement ne devrait jamais être null.
Expliquer pourquoi ils ne peuvent pas être null. Si QuestionList est List<Type> de longueur 1, il n'y a pas de raison que je pense de l'arrêt de QuestionList[0] d'être nulle. De même, 'Type' dans mon exemple peut encore avoir la propriété de "Questions" non initialisé. c'est à dire null.
Ils ne peuvent jamais être nulle parce que c'est comment Where et SelectMany travail. Si l'entrée est nulle, ils lancent une exception, et si ce n'est pas null, le résultat sera soit une séquence d'éléments, ou une séquence vide. Il va jamais être null. En règle générale, vous devriez éviter de null valeurs pour les collections ou des séquences, il suffit d'utiliser un regroupement vide à la place.
questions est ce que Enumerable.SelectMany ou Queryable.SelectMany décide de rentrer. Et qui est garanti pour être non-nulle.

OriginalL'auteur Pricey | 2013-01-22