I'm getting a null exception while iterating over a collection of non nullable objects.
List<ReconFact> facts = new List<ReconFact>();
// ...populating facts
int count = 0;
foreach (var fact in facts)
{
Console.WriteLine(++count);
try
{
context = AddToContext(context, fact, count, 100, true);
}
catch (Exception e)
{
Console.WriteLine(e.Message); // Null Exception Raised at some point
}
}
How is that possible ? I didn't know that iterating over a list could provide null elements is that a normal behaviour ? Is it possible to add a null item when the list is populated ?
Yes, it's possible to add null to a List<T> where T is a reference type. Nothing prevents someone from:
List<ReconFact> facts = new List<ReconFact>();
facts.Add(null);
You could simply check that first:
foreach (var fact in facts.Where(f => f != null))
// ...
Yes, a List can contain nulls, so can arrays and several other collections.
It won't break the iterating itself, but it will break any code inside the { } that relies on the element not being null.
List<String> s = new List<String>();
s.Add("foo");
s.Add(null);
s.Add("bar");
Edit: Wait, what do you mean by "non-nullable objects"?
I think the problem is in your logic. You just initialize the list of Recontent named fact.
So all time its count is 0. Please check that.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am interfacing to an API that exposes the following function:
IEnumerable<Color?> getColors(long Id);
I call the function:
IEnumerable<System.Drawing.Color?> colList = getColors(1);
The list is not null when the function returns. However, when I attempt to iterate through the list:
foreach (System.Drawing.Color col in colList)
{...}
I get nothing. The loop is not entered.
What is the correct way to iterate through the list?
Edit: I finally figured out how to get a list count with this bit of voodoo:
int colCount = colList.Count<System.Drawing.Color?>();
The count is indeed zero, as has been suggested. I'm now off to the provider of the API to ask why so?
Thank you to all who provided positive and constructive suggestions.
The iterator is empty. That is why it does not enter the loop.
However, please note that you do not have a nullable type in your loop:
IEnumerable<System.Drawing.Color?> colList = getColors(1);
// System.Drawing.Color is not nullable:
foreach (System.Drawing.Color col in colList)
{
Console.WriteLine(col);
}
Which will result in an InvalidOperationException when a null comes (because it cannot cast null to System.Drawing.Color). Use a System.Drawing.Color? (or use var) instead.
Example:
static void Main()
{
foreach (var col in getColors(1))
{
Console.WriteLine(col == null);
}
Console.ReadLine();
}
static IEnumerable<System.Drawing.Color?> getColors(long Id)
{
yield return null;
}
Outputs True
About using the extension method Count, know that it might be iterating over the IEnumerable<Color?>※. In that case, I would suggest to use ToArray and check the size of the array. With that said, know that a IEnumerable<Color?> could also be infinite.
※: As per the reference source, Count could be casting to ICollection<TSource> or ICollection to get the Count property from there. Otherwise it will iterate.
Trivial example of infinite IEnumerable<Color?>:
static IEnumerable<System.Drawing.Color?> getColors(long Id)
{
while (true)
{
yield return null;
}
}
If you need to handle the empty case, another option is to set a variable inside the loop. If the variable is set, you know it is not empty.
Example:
bool isEmpty = true;
foreach (var col in getColors(1))
{
isEmpty = false;
// ...
}
if (isEmpty)
{
// ...
}
As Dmitry Bychenko points out, you might be interested in OfType.
Addendum:
The IEnumerable<T> interface has only a GetEnumerator method. However, C# supports extension methods, and you will find a large number of extension methods for IEnumerable<T> in System.Linq.Enumerable, including Count, ToArray and OfType.
To use these extension methods add using System.Linq; to your code file. Example:
using System.Linq;
// ...
static void Main()
{
var colors = getColors(1).ToArray();
// ...
}
Or call them as regular methods. Example:
static void Main()
{
var colors = System.Linq.Enumerable.ToArray(getColors(1));
// ...
}
These last two code examples are equivalent. Usually the former is prefered.
As you can see, Color? is nullable, when Color is not. If you want to get only not null values (Color), you can add Linq OfType<T>():
using System.Linq; // OfType<T>() is declared as Linq extension method
...
// loop over not null cols only
foreach (System.Drawing.Color col in colList.OfType<System.Drawing.Color>()) {
...
}
Demo:
using System.Linq;
...
List<System.Drawing.Color?> list = new List<System.Drawing.Color?>() {
System.Drawing.Color.Red,
System.Drawing.Color.Black,
null, // <- should be excluded
System.Drawing.Color.Blue,
};
foreach (System.Drawing.Color col in list.OfType<System.Drawing.Color>())
Console.WriteLine(col);
Outcome:
Color [Red]
Color [Black]
Color [Blue]
This is not in relation to the nullable values of the IEnumerable. If you run this code (https://rextester.com/):
List<String> list = new List<String>();
list.Add(null);
list.Add("asd1");
list.Add(null);
list.Add("asd2");
list.Add(null);
IEnumerable<String> enumerable = list.AsEnumerable();
foreach(var item in enumerable)
{
Console.WriteLine('"' + item + '"');
}
The output will be:
""
"asd1"
""
"asd2"
""
So as you can see the null values are not removed from the IEnumerable and we still iterate through the empty values. More than likely the IEnumerable is empty.
I have a very simple piece code which contains a foreach loop:
foreach(var item in list) {
var valueForPropertyA = getPropertyAValue(item?.Id ?? 0);
if(valueForPropertyA == null) {
continue;
}
item.PropertyA = new PropertyADto(valueForPropertyA);
}
We also have some automatic code inspection tool which gives me the following warning on the above code:
'item' is null on at least one execution path
Is it ever possible that an item in a list is null or am I misinterpreting the warning?
Sure, foreach doesn't skip items that are null. Then you'd get a NullReferenceException at the line item.PropertyA = new PropertyADto(valueForPropertyA);.
Instead you could use
foreach(var item in list.Where(i => i != null))
{
// ...
}
To answer your primary question, yes, if the IEnumerable being enumerated by the foreach loop contains reference types, they can be null. For example, List<string> may contain null entries, as string can be null.
I suspect the reason you are receiving the'item' is null on at least one execution path message is due to the use of the null propagating operator on the following line:
var valueForPropertyA = getPropertyAValue(item?.Id ?? 0);
Later on you call:
item.PropertyA = new PropertyADto(valueForPropertyA);
The first line's item?.Id indicates that you expect item might be null. The second line does not include the null propagating operator, so the code analysis tool is warning you that while item might be null on the first line, you are not handling this possibility on the second line.
Items of reference and nullable value types can be null - but you can skip them manually
foreach(var item in list.Where(x => x != null))
What would be the optimal way to get the only element in the list? if it is not equal to one, log it.
Is it better to use a try..catch block against Single? or use Count?
try
{
var item = list.Single();
}
catch(System.InvalidOperationException)
{
//log
Console.WriteLine("The collection does not contain exactly one element.");
}
or
if(list.Count!=1)
{
//log
Console.WriteLine("The collection does not contain exactly one element.");
}
var item = list.FirstOrDefault();
Well, try {...} catch {...} will do stack trace and it means much overhead.
So the 2nd possibility is a better one (Count is a good choice when working with List<T>). Actually, you don't need Linq at all:
// list.Count is just a integer field, a very cheap comparison
if (list.Count != 1) {
// 0 or many items (not a single one)
...
}
else {
// list contains exactly one item
var item = list[0];
...
}
beware traps like this:
List<Object> list = new List<Object>() {
null,
123
};
// item == null even if list has TWO items
var item = list.FirstOrDefault();
if (list == null || list.Count != 1)
{
Console.WriteLine("The collection does not contain exactly one element.");
}
As Iridium commented, Single() or SingleOrDefault() might not be the best choice here because it throws an exception if there is more than one element or the list equals null.
I replaced that with a null-check and a comparison with count
This way is better
if(list.Count!=1)
{
//log
Console.WriteLine("The collection does not contain exactly one element.");
}
var item = list.FirstOrDefault();
I often come across code like the following:
if ( items != null)
{
foreach(T item in items)
{
//...
}
}
Basically, the if condition ensures that foreach block will execute only if items is not null. I'm wondering if the if condition is really needed, or foreach will handle the case if items == null.
I mean, can I simply write
foreach(T item in items)
{
//...
}
without worrying about whether items is null or not? Is the if condition superfluous? Or this depends on the type of items or maybe on T as well?
You still need to check if (items != null) otherwise you will get NullReferenceException. However you can do something like this:
List<string> items = null;
foreach (var item in items ?? new List<string>())
{
item.Dump();
}
but you might check performance of it. So I still prefer having if (items != null) first.
Based on Eric's Lippert suggestion I changed code to:
List<string> items = null;
foreach (var item in items ?? Enumerable.Empty<string>())
{
item.Dump();
}
Using C# 6 you could use the new null conditional operator together with List<T>.ForEach(Action<T>) (or your own IEnumerable<T>.ForEach extension method).
List<string> items = null;
items?.ForEach(item =>
{
// ...
});
The real takeaway here should be a sequence should almost never be null in the first place. Simply make it an invariant in all of your programs that if you have a sequence, it is never null. It is always initialized to be the empty sequence or some other genuine sequence.
If a sequence is never null then obviously you don't need to check it.
Actually there is a feature request on that here: https://github.com/dotnet/csharplang/discussions/1081#issuecomment-443209795
And the response is quite logical:
I think that most foreach loops are
written with the intent of iterating a
non-null collection. If you try
iterating through null you should get
your exception, so that you can fix
your code.
You could always test it out with a null list... but this is what I found on the msdn website
foreach-statement:
foreach ( type identifier in expression ) embedded-statement
If expression has the value null, a System.NullReferenceException is thrown.
You can encapsulate the null check in an extension method and use a lambda:
public static class EnumerableExtensions {
public static void ForEach<T>(this IEnumerable<T> self, Action<T> action) {
if (self != null) {
foreach (var element in self) {
action(element);
}
}
}
}
The code becomes:
items.ForEach(item => {
...
});
If can be even more concise if you want to just call a method that takes an item and returns void:
items.ForEach(MethodThatTakesAnItem);
It is not superflous. At runtime items will be casted to an IEnumerable and its GetEnumerator method will be called. That will cause a dereferencing of items that will fail
You do need this. You'll get an exception when foreach accesses the container to set up the iteration otherwise.
Under the covers, foreach uses an interface implemented on the collection class to perform the iteration. The generic equivalent interface is here.
The foreach statement of the C#
language (for each in Visual Basic)
hides the complexity of the
enumerators. Therefore, using foreach
is recommended instead of directly
manipulating the enumerator.
The test is necessary, because if the collection is null, foreach will throw a NullReferenceException. It's actually quite simple to try it out.
List<string> items = null;
foreach(var item in items)
{
Console.WriteLine(item);
}
the second will throw a NullReferenceException with the message Object reference not set to an instance of an object.
As mentioned here you need to check is it not null.
Do not use an expression that evaluates to null.
The accepted answer is getting old.
Nowadays, nullable types are used extensively and help the compiler understand what you're trying to achive (and avoid mistakes).
Which means that your list could be this :
List<Item>? list
...OR... this :
List<Item> list
You'll need to check for nullability only for the former case.
Same thing goes for items:
List<Item?> list
...OR... this :
List<Item> list
You'll need to check for nullability of items only for the former case.
And of course finally you have this :
List<Item?>? list
where anything (list and items) could potentially be null.
==================
EDIT: A picture is better than 1,000 words
In C# 6 you can write sth like this:
// some string from file or UI, i.e.:
// a) string s = "Hello, World!";
// b) string s = "";
// ...
var items = s?.Split(new char[] { ',', '!', ' ' }) ?? Enumerable.Empty<string>();
foreach (var item in items)
{
//..
}
It's basically Vlad Bezden's solution but using the ?? expression to always generate an array that is not null and therefore survives the foreach rather than having this check inside the foreach bracket.
So I frequently run into this situation... where Do.Something(...) returns a null collection, like so:
int[] returnArray = Do.Something(...);
Then, I try to use this collection like so:
foreach (int i in returnArray)
{
// do some more stuff
}
I'm just curious, why can't a foreach loop operate on a null collection? It seems logical to me that 0 iterations would get executed with a null collection... instead it throws a NullReferenceException. Anyone know why this could be?
This is annoying as I'm working with APIs that aren't clear on exactly what they return, so I end up with if (someCollection != null) everywhere.
Well, the short answer is "because that's the way the compiler designers designed it." Realistically, though, your collection object is null, so there's no way for the compiler to get the enumerator to loop through the collection.
If you really need to do something like this, try the null coalescing operator:
int[] array = null;
foreach (int i in array ?? Enumerable.Empty<int>())
{
System.Console.WriteLine(string.Format("{0}", i));
}
A foreach loop calls the GetEnumerator method.
If the collection is null, this method call results in a NullReferenceException.
It is bad practice to return a null collection; your methods should return an empty collection instead.
There is a big difference between an empty collection and a null reference to a collection.
When you use foreach, internally, this is calling the IEnumerable's GetEnumerator() method. When the reference is null, this will raise this exception.
However, it is perfectly valid to have an empty IEnumerable or IEnumerable<T>. In this case, foreach will not "iterate" over anything (since the collection is empty), but it will also not throw, since this is a perfectly valid scenario.
Edit:
Personally, if you need to work around this, I'd recommend an extension method:
public static IEnumerable<T> AsNotNull<T>(this IEnumerable<T> original)
{
return original ?? Enumerable.Empty<T>();
}
You can then just call:
foreach (int i in returnArray.AsNotNull())
{
// do some more stuff
}
It is being answer long back but i have tried to do this in the following way to just avoid null pointer exception and may be useful for someone using C# null check operator ?.
//fragments is a list which can be null
fragments?.ForEach((obj) =>
{
//do something with obj
});
Another extension method to work around this:
public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
{
if(items == null) return;
foreach (var item in items) action(item);
}
Consume in several ways:
(1) with a method that accepts T:
returnArray.ForEach(Console.WriteLine);
(2) with an expression:
returnArray.ForEach(i => UpdateStatus(string.Format("{0}% complete", i)));
(3) with a multiline anonymous method
int toCompare = 10;
returnArray.ForEach(i =>
{
var thisInt = i;
var next = i++;
if(next > 10) Console.WriteLine("Match: {0}", i);
});
Because a null collection is not the same thing as an empty collection. An empty collection is a collection object with no elements; a null collection is a nonexistent object.
Here's something to try: Declare two collections of any sort. Initialize one normally so that it's empty, and assign the other the value null. Then try adding an object to both collections and see what happens.
Just write an extension method to help you out:
public static class Extensions
{
public static void ForEachWithNull<T>(this IEnumerable<T> source, Action<T> action)
{
if(source == null)
{
return;
}
foreach(var item in source)
{
action(item);
}
}
}
It is the fault of Do.Something(). The best practice here would be to return an array of size 0 (that is possible) instead of a null.
Because behind the scenes the foreach acquires an enumerator, equivalent to this:
using (IEnumerator<int> enumerator = returnArray.getEnumerator()) {
while (enumerator.MoveNext()) {
int i = enumerator.Current;
// do some more stuff
}
}
I think the explanation of why exception is thrown is very clear with the answers provided here. I just wish to complement with the way I usually work with these collections. Because, some times, I use the collection more then once and have to test if null every time. To avoid that, I do the following:
var returnArray = DoSomething() ?? Enumerable.Empty<int>();
foreach (int i in returnArray)
{
// do some more stuff
}
This way we can use the collection as much as we want without fear the exception and we don't polute the code with excessive conditional statements.
Using the null check operator ?. is also a great approach. But, in case of arrays (like the example in the question), it should be transformed into List before:
int[] returnArray = DoSomething();
returnArray?.ToList().ForEach((i) =>
{
// do some more stuff
});
SPListItem item;
DataRow dr = datatable.NewRow();
dr["ID"] = (!Object.Equals(item["ID"], null)) ? item["ID"].ToString() : string.Empty;