3

I am trying to get a list item that contains a certain string and I am using this code:

string myListLine= myList.FirstOrDefault(stringToCheck => stringToCheck.Contains("mystring "));

All works well but if the list does not contain a particular string it throws an error:

object reference not set to an instance of an object

I think that I should somehow validate if the string first exists but not sure what would be the best approach.

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
Cat Hariss
  • 123
  • 10
  • You need to check if `myList` contains data first - otherwise it will throw NRE. – Tetsuya Yamamoto Nov 23 '17 at 07:18
  • Yes. Because `FirstOrDefault` returns `null` if no item matches – Gilad Green Nov 23 '17 at 07:18
  • 1
    IMHO, It's not (really) a duplicate of that, nor should this question be closed `var myList = new List(){"foo","Bar",null, "the mystring"};` – EdSF Nov 23 '17 at 08:31
  • @EdSF I agree with you, but the canonical duplicate is actually telling how to debug your programm to find the error. The question should may be rephrased into : "How to check for `null` item in List". Which might bring up a different duplicate :) – Mong Zhu Nov 23 '17 at 08:36

5 Answers5

5

if the list does not contain a particular string it throws an error:

That is not correct. The exception is thrown, because you have a null value inside your list! If all of your items in the list are valid strings then there will be no exception thrown. In this case FirstOrDefault will simply return null.

I think that I should somehow validate if the string first exists

You can check whether it is null the oldscool way first and combine it with an logical AND && with the Contains method

string myListLine= myList.FirstOrDefault(stringToCheck => 
           stringToCheck != null && stringToCheck.Contains("mystring "));

This way the second Contains will not be evaluated if the first condition evaluates to FALSE

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
  • This seems to be the simplest and most logical solution, as expected. Solved my problem perfectly. Thank you! – Cat Hariss Nov 23 '17 at 10:33
  • you are very welcome. Glad I could help. How do you get those `null` values into your string list ? – Mong Zhu Nov 23 '17 at 10:39
  • Well, I never said my list has `null` values, you just assumed that, but when I try to get a list line containing a certain string that does not exist, the error is thrown. So I guess that even if you intended to check if the list values are null or not, your solution works also for checking if the string exists anywhere within my list elements. – Cat Hariss Nov 23 '17 at 12:03
  • @CatHariss actually you did say so, because the only scenario in which your code can throw an **object reference not set to an instance of an object** error is when you try to call `Contains` on an element in your List that is `null`! In all other cases you get either a different exception thrown or you simply get a `null` as return value from `FirstOrDefault`. My code ensures that `Contains` will only be called on instantiated string objects. Irrespective of the point weather they contain the searched string. – Mong Zhu Nov 23 '17 at 12:10
1

You can use the safe navigation operator and the null-coalescing operator to fix this:

System.Collections.Generic.List<string> myList = new System.Collections.Generic.List<string> { null, "Test123" };
string myListLine = myList.FirstOrDefault(stringToCheck => stringToCheck?.Contains("mystring ") ?? false);

The problem occurs if you're calling a method on a null list entry.

Note: If the list is empty FirstOrDefault returns null.

Hope that helps.

Moerwald
  • 10,448
  • 9
  • 43
  • 83
1

Your code simply goes through myList, for each item, it checks if it contains "mystring ".

Only reason you may get a null reference while running that line is your list myList is null. It wouldn't get any error if it is empty.

if you get a null reference after that line, that would mean that myListLine is null, which would mean myList did not contain any items that matched "mystring ".

To make sure you do not get a null reference error with myListLine you should check if it is null before accessing it by using something like this;

if( myListLine != null ){
    <Do something to myListLine>
} else {
    <list doesnt contain the correct string, alert user.>
}
Hakan Maac
  • 54
  • 7
1

I think this sample code of mine is one of the safest way by accessing the myList object. If it is null then return an indicator that value was not found or empty.

List<string> myList = new List<string>() 
{
  "name","adress","phoneNumber"
};
myList.RemoveAll(item => item == null);
string myListLine = myList.FirstOrDefault(stringToCheck => stringToCheck.Contains("myString")) ?? "Not found/Empty";
davinceleecode
  • 777
  • 3
  • 10
  • 31
  • how is this solution supposed to avoid the NullReferenceException? If `myList` has a `null` item it still will throw the exception – Mong Zhu Nov 23 '17 at 08:25
  • " is one of the safest way by accessing the myList object" sorry but it is not. "by accessing the myList object. If it is null " if `myList` is null it will throw an ArgumentNullException. It only works for the case that now item was found. But you described that case a little ambiguously. Sorry mate – Mong Zhu Nov 23 '17 at 08:39
  • 2
    But how about removing null elements before accessing the whole object? – davinceleecode Nov 23 '17 at 08:45
  • 3
    this would work. On the other hand this will modify the collection, and we don't know whether this will influence further processing of OP 's code. If for example he needs the `Count` of the list. but basically this would avoid the exception – Mong Zhu Nov 23 '17 at 10:12
1

A variation:

var myList = new List<string>(){"foo","Bar", null,"the mystring"};
string myListLine = myList.FirstOrDefault(s => s == null? false : s.Contains("mystring"));

Same notes as already mentioned regarding FirstOrDefault being null if empty list or no match (does not Contains)

EdSF
  • 11,753
  • 6
  • 42
  • 83