Параметр в LINQ, где стал нулевым, что для меня не имеет смысла. Почему это произошло?

#c# #linq

#c# #linq

Вопрос:

Я долгое время писал запросы на C # и LINQ. Я хочу просмотреть временный список, ища совпадающие значения в 1 поле (с именем Model). В спецификации говорится, что если есть соответствующая модель, то ее нельзя добавлять в список. Итак, я удаляю повторяющиеся модели и добавляю только уникальные в список, который возвращается. Вот функция, которую я написал для этого:

 private List<InstrumentModel> EnsureInstrumentModelListUnique(List<InstrumentModel> instrumentModels)
{
    var tmpList = new List<InstrumentModel>();

    if (instrumentModels == null || instrumentModels.Count <= 1)
    {
        //nothing to see here folks, move on
        return instrumentModels;
    }

    for (int i = 0; i < instrumentModels.Count; i  )
    {
        if (i == 0)
        {
            tmpList.Add(instrumentModels[0]);
        }
        else
        {
            //get current model
            string model = instrumentModels[i].Model;

            //check to see if model is somewhere in the list
            var rec = tmpList.Where(t => t.Model == model).FirstOrDefault();

            //if it isn't there, put it in
            if (rec == null)
            {
                tmpList.Add(rec);
            }
        }
    }

    return tmpList;
}
 

Он проходит for цикл 3 раза, прежде чем произойдет сбой. Он вылетает при t.Model in tmpList.Where(t => t.Model == model).FirstOrDefault() , утверждая, что t это null .

Я не понимаю, как t значение null на третьей итерации цикла. Таблица, из которой instrumentModels происходит from, содержит 5 записей. Все записи имеют что-то в столбце модели.

Вот определение InstrumentModel, в которое для краткости включены только соответствующие столбцы:

 [Table("app.InstrumentModel")]
[DebuggerDisplay("ID == {ID}, Model == {Model}, Inactive == {Inactive}")]
public partial class InstrumentModel
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public InstrumentModel()
    {
        Instruments = new HashSet<Instrument>();
        PersonnelCertifications = new HashSet<PersonnelCertification>();
    }

    [Key]
    public long ID { get; set; }

    [Required]
    [StringLength(30)]
    public string Model { get; set; }
}
 

Я работаю с WPF, .NET Framework 4.5.2, VS 2019

Комментарии:

1. if (rec == null) { tmpList.Add(rec); } прокомментировано «если его там нет, вставьте его» . Это не то, что это делает.

2. Я бы сказал, что подобные комментарии на самом деле вредны, потому что они могут помешать вам прочитать то, что вы на самом деле написали.

Ответ №1:

Как указал @madreflection, проблема здесь:

 //check to see if model is somewhere in the list
var rec = tmpList.Where(t => t.Model == model).FirstOrDefault();

//if it isn't there, put it in
if (rec == null)
{
    tmpList.Add(rec);
}
 

Я полагаю, что в этом случае вы вставляете rec , когда должны вставлять model .

Код проще с Any помощью . Если вы сделаете это таким образом, нет нулевой переменной, в которой можно запутаться.

 bool found = tmpList.Any(t => t.Model == model);

if (!found)
{
    tmpList.Add(model);
}
 

Комментарии:

1. Спасибо, Джон Ву и madreflection. Теперь я вижу свою ошибку. Я был слишком близко к нему, поэтому я его не видел. Нужны другие пары глаз, чтобы рассказать мне об этом. Теперь это очевидно. Кроме того, спасибо, что сообщили мне об этой Any фразе. Я предполагаю, что это аналогично SQL EXISTS .