1

I am receiving the following error when trying to access an XML element that doesnt exist using linq:

A first chance exception of type 'System.NullReferenceException' occurred in Test.exe System.NullReferenceException: Object reference not set to an instance of an object.

bool exists = website.Parent
            .Element("Exclusions")
            .Elements("Exclusion")
            .Where(x => thisKeyword.ToUpper().Contains((string)x.Value.ToUpper() ?? "~"))
            .Any();

I can remedy the issue by simply using .Where(x => thisKeyword.Contains((string)x))

But I need to convert both thisKeyword and the XML element value (if it exists) to upper case to get a case-insensitive comparison.

I was under the impression that ?? "~" meant that "if whats the left is null use what is to the right. So in this case x should become tilde, and therefore not validate against thisKeyword (as it wont ever contain tilde). A crude method I agree...but it doesn't even work.

How can I protect against the NullReferenceException?

James
  • 646
  • 2
  • 9
  • 22
  • 2
    Possible duplicate of [What is a NullReferenceException, and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Tony Hopkinson Mar 12 '17 at 23:09
  • Look at what is null, thisKeyword, x, or x.Value will kill you. Have to do a null check first. – Tony Hopkinson Mar 12 '17 at 23:11
  • 1
    I think that you can use the following code `thisKeyword?.ToUpper().Contains((string)x?.Value.ToUpper() ?? "~")` for checking that both aren't null – ganchito55 Mar 12 '17 at 23:12

1 Answers1

1

Assuming that x.Value is null and thisKeyword is known to be non-null:

The crash is happening because the ?? operator is trying to check whether the value returned by ToUpper() is null. However, it can't call ToUpper() because x.Value does not exist.

In C# version 6 or later you can use the null propagation operator, ?., which accesses a property if and only if the object is non-null:

.Where(x => thisKeyword.ToUpper().Contains(
            (string)x.Value?.ToUpper() ?? "~")

Alternatively, just use a separate Where clause to check that x.Value is non-null:

.Where(x => x.Value != null)
.Where(x => thisKeyword.ToUpper().Contains(x.Value.ToUpper())

As an aside, you could put the condition inside the Any() clause instead:

.Elements("Exclusion")
.Any(x => x.Value != null && thisKeyword.ToUpper().Contains(x.Value.ToUpper())

And you don't necessarily need to convert to upper case either:

.Any(x => x.Value != null &&
          thisKeyword.IndexOf(x.Value,
             StringComparison.InvariantCultureIgnoreCase) > 0)
Alistair Green
  • 422
  • 3
  • 9
  • 1
    You are on the right track, but instead of messing around with the Elvis operator you can instead use something far simpler - the [string.Equals(string, string, comparisonType)](https://msdn.microsoft.com/en-us/library/t4411bks(v=vs.110).aspx) static method.It is tolerant of nulls, and you can specify a case insensitive check (which is the most common reason why people do a ToUpper() or ToLower() before checking). – slugster Mar 12 '17 at 23:59
  • Thanks for this. It looks like I cannot use the Value?. property so I must be on an older version of C#. My next issue is how I should deal with NullReferenceException if .Elements("Exclusion") and .Element("Exclusions") do not exist in the XML? – James Mar 13 '17 at 09:18