1

I am using the following LINQ to compare two lists of objects.

var upd = newObj.Where(wb => oldObj.Any(db => 
                           (db.AnswerId == wb.AnswerId) &&
                           (db.Number != wb.Number || !db.Text.Equals(wb.Text))))
                .ToList(); 

When the AnswerId matches then I look to see if the object.Number or the object.Text is different.

However this is giving me an:

Object reference not set to an instance of an object. 

I think the problem is when the old object has an answer with Text field set to null so

!db.Text.Equals(wb.Text) 

fails to work the way I expected.

Is there some way I could change the above comparison so it shows true if the text is different or if the old Text was null and also if the values of the field named Correct change?

FYI Here's the object I am using:

public class Answer     {
    public int AnswerId { get; set; }
    public int Number { get; set; }
    public int QuestionId { get; set; }
    public Nullable<bool> Correct { get; set; }
    public Nullable<bool> Response { get; set; }
    public string Text { get; set; }

}
Ondrej Janacek
  • 12,486
  • 14
  • 59
  • 93

4 Answers4

1

You can just use db.Text != wb.Text. It isn't calling any string methods so you won't have null references.

jAC
  • 5,195
  • 6
  • 40
  • 55
Paweł Reszka
  • 1,557
  • 4
  • 20
  • 41
  • Thanks. Do you have any ideas why it was originally suggested to use .Equals ? –  Aug 28 '13 at 07:51
  • In short: `==` compares if the refernce is equal, `Equals()` compares if the value is equal. For more info: http://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals – jAC Aug 28 '13 at 07:52
  • I know that it's the only way in Java to compare strings. But in c# it's not a problem:) – Paweł Reszka Aug 28 '13 at 07:54
  • @Pawel - I think Dave is saying this might throw a null ref exception. Can you confirm. I saw you just edited to add that it won't. Just want to be sure. Thanks –  Aug 28 '13 at 07:58
  • @Melina Why don't you simply test it? – jAC Aug 28 '13 at 07:58
  • Generally, `.Equals` behaves oddly in LINQ. It's a method on the C# class `Object`, which means that it has to create an instance of `object` in the query to use that method, which isn't always possible. As a rough rule, when using LINQ forget about the distinction between `==` and `.Equals()` and just use `==`. – anaximander Aug 28 '13 at 07:59
  • It won't throw it. It's like this" "abc"!=null. So it works fine. What you did was like that: null.Equals("abc"). – Paweł Reszka Aug 28 '13 at 08:00
0

You could try to use Equals in the following way:

Equals(db.Text, wb.Text);
dave
  • 223
  • 2
  • 9
  • Would this be better than Pawel's suggestion? I am just wondering how this would act if one of the fields was null? –  Aug 28 '13 at 07:54
  • This will not throw null ref exception when one of the Text fields was null. – dave Aug 28 '13 at 07:55
  • Sorry, if I was unclear... Pawel's suggestion doesn't throw exception, and results in the exactly same behaviour (in this case). – dave Aug 28 '13 at 08:03
0

I sometimes use the null-coalescing operator to generate empty default collections.

var filteredThings = (collection ?? new Thing[0]).Where(p => Thing.Desirable);

Not massively performant but it has its places if you pre-initialise the empty array.

Gusdor
  • 14,001
  • 2
  • 52
  • 64
0

You were right assuming that the cause is that Text is null. That's a common problem when comparing objects inside LINQ expressions. As No One pointed out the solution is usually to additionally compare with null. However in your case the solution is simpler: Just compare using != (Text is a string, therefore != is the same as !db.Text.Equals):

var upd = newObj.Where(wb => oldObj.Any(db => (db.AnswerId == wb.AnswerId) && 
   (db.Number != wb.Number || db.Text != wb.Text))).ToList();
Jürgen Bayer
  • 2,993
  • 3
  • 26
  • 51