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;
Related
If I want to perform actions such as .Where(...) or .Max(...), I need to make sure the list is not null and has a count greater than zero. Besides doing something such as the following everytime I want to use the list:
if(mylist != null && mylist.Count > 0)
{...}
is there something more inline or lambda like technique that I can use? Or another more compressed technique?
public static class LinqExtensions
{
public static bool IsNullOrEmpty<T>(this IEnumerable<T> items)
{
return items == null || !items.Any();
}
}
You can then do something like
if (!myList.IsNullOrEmpty())
....
My general preference is to have empty list instances, instead of null list variables. However, not everyone can cajole their co-workers into this arrangment. You can protect yourself from null list variables using this extension method.
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
return source ?? Enumerable.Empty<T>();
}
Called by:
Customers result = myList.EmptyIfNull().Where(c => c.Name == "Bob");
Most linq methods work on empty collections. Two methods that don't are Min and Max. Generally, I call these methods against an IGrouping. Most IGrouping implementations have at least one element (for example, IGroupings generated by GroupBy or ToLookup). For other cases, you can use Enumerable.DefaultIfEmpty.
int result = myList.EmptyIfNull().Select(c => c.FavoriteNumber).DefaultIfEmpty().Max();
Don't let the list be null
Ensure the object is always in a valid state. By ensuring the list is never null, you never have to check that the list is null.
public class MyClass
{
private readonly IEnumerable<int> ints;
public MyClass(IEnumerable<int> ints)
{
this.ints = ints;
}
public IEnumerable<int> IntsGreaterThan5()
{
return this.ints.Where(x => x > 5);
}
}
Even if this list were empty, you'd still get a valid IEnumerable<int> back.
Max and Min overloads with Nullable types
That still doesn't solve the "Max" and "Min" problems though. There's an overload of Max and Min that take selectors. Those selector overloads can return nullable ints, so your max method becomes this:
this.ints.Max(x => new int?(x));
Therefore, you run Max and check to see if you've gotten a null value or an integer back. voila!
Other Options
Custom Extension Methods
You could also write your own extension methods.
public static MinMaxHelper()
{
public static int? MaxOrDefault(IEnumerable<int> ints)
{
if(!ints.Any())
{
return null;
}
return ints.Max();
}
public static int MaxOrDefault(IEnumerable<int> ints, int defaultValue)
{
if(!ints.Any())
{
return defaultValue;
}
return ints.Max();
}
}
Overriding Linq Extension Methods
And finally, remember that the build in Linq extension methods can be overriden with your own extension methods with matching signatures. Therefore, you could write an extension method to replace .Where(...) and .Max(...) to return null (or a default value) instead of throwing an ArgumentNullException if the Enumerable is null.
Use empty collections instead of null collections. Where will work just fine against an empty collection, so you don't need to ensure that Count > 0 before calling it. You can also call Max on an empty collection if you do a bit of gymnastics first.
For IEnumerable<T> use Enumerable.Empty<T>()
For T[] use new T[0]
For List<T> use new List<T>()
You could try myList.Any() instead of .Count, but you'd still need to check for null.
If there is a risk of your list being null you will alway have to check that before calling any of its methods but you could use the Any() method rather than count. This will return true as soon as it counts one item regardless if there is one or more item in the list. This saves iterating over the entire list which is what Count will do:
if(mylist != null && mylist.Any())
{...}
You can use ?? operator which converts null to the value you supply on the right side:
public ProcessList(IEnumerable<int> ints)
{
this.ints = ints ?? new List<int>();
}
By the way: It is not a problem to process an empty list using LINQ.
You don't need to check Count to call Where. Max needs a non-empty list for value types but that can be overcome with an inline cast, eg
int? max = new List<int>().Max(i => (int?)i); // max = null
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.
For my function
IEnumerable<CallbackListRecord> LoadOpenListToProcess(CallbackSearchParams usp);
This line errors when the sequence contains no elements (as it should)
CallbackListRecord nextRecord = CallbackSearch.LoadOpenListToProcess(p).First();
I have changed it to the following
CallbackListRecord nextRecord = null;
IEnumerable<CallbackListRecord> nextRecords = CallbackSearch.LoadOpenListToProcess(p);
if (nextRecords.Any())
{
nextRecord = nextRecords.First();
}
Are there better, easier or more elegant ways to determine if the IEnumerable sequence has no elements?
You should try to avoid enumerating it more times than necessary (even if short-circuited, like First and Any) - how about:
var nextRecord = CallbackSearch.LoadOpenListToProcess(p).FirstOrDefault();
if(nextRecord != null) {
// process it...
}
This works well with classes (since you can just compare the reference to null).
You can shorten the code to the following
var nextrecord = CallbackSearch.LoadOpenListToProcess(p).FirstOrDefault();
nextrecord will either contain the First element if there was one or null if the collection was empty.
If you are anticipating that there could be null values in the sequence, you could handle the enumerator yourself.
var enumerator = CallbackSearch.LoadOpenListToProcess(p).GetEnumerator();
if (enumerator.MoveNext()) {
var item = enumerator.Current;
...
}
You could add an extension method like this:
public static class Extensions
{
public static bool HasElements<T>(this IEnumerable<T> collection)
{
foreach (T t in collection)
return true;
return false;
}
}
I've got this:
private IEnumerable _myList;
I need to get a count off of that object. I was previously typing _myList to an array and getting the length, but now we are using this same bit of code with a different kind of object. It's still a Collection type (it's a strongly typed Subsonic Collection object), and everything works great, except for the bit that we need to get the total number of items in the object.
I've tried typing it to CollectionBase, and many many other types, but nothing works that will let me get a .Count or .Length or anything like that.
Can anyone point me in the right direction?
EDIT: I'm not using 3.5, I'm using 2. So, anything dealing with Linq won't work. Sorry for not posting this earlier.
Is this actually IEnumerable instead of IEnumerable<T>? If so, LINQ won't help you directly. (You can use Cast<T>() as suggested elsewhere, but that will be relatively slow - in particular, it won't be optimised for IList/IList<T> implementations.)
I suggest you write:
public static int Count(this IEnumerable sequence)
{
if (sequence == null)
{
throw new ArgumentNullException("sequence");
}
// Optimisation: won't optimise for collections which
// implement ICollection<T> but not ICollection, admittedly.
ICollection collection = sequence as ICollection;
if (collection != null)
{
return collection.Count;
}
IEnumerator iterator = sequence.GetEnumerator();
try
{
int count = 0;
while (iterator.MoveNext())
{
// Don't bother accessing Current - that might box
// a value, and we don't need it anyway
count++;
}
return count;
}
finally
{
IDisposable disposable = iterator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
The System.Linq.Enumerable.Count extension method does this for a typed IEnumerable<T>.
For an untyped IEnumerable try making your own extension:
public static int Count(this IEnumerable source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
ICollection collectionSource = source as ICollection;
if (collectionSource != null)
{
return collectionSource.Count;
}
int num = 0;
IEnumerator enumerator = source.GetEnumerator();
//try-finally block to ensure Enumerator gets disposed if disposable
try
{
while (enumerator.MoveNext())
{
num++;
}
}
finally
{
// check for disposal
IDisposable disposableEnumerator = enumerator as IDisposable;
if(disposableEnumerator != null)
{
disposableEnumerator.Dispose();
}
}
return num;
}
If you're using .NET 3.5, you can use Enumerable.Count() to get the count from any IEnumerable<T>.
This will not work off a non-generic IEnumerable, though - it requires IEnumerable<T>.
This should work, though, since Subsonic's collection classes implement the appropriate interfaces for you. You'll need to change your definition from IEnumerable to IEnumerable<MyClass>.
LINQ provides a Count() extension method.
using System.Linq;
...
var count = _myList.Count();
The type you use is IEnumerable, which doesn't have a Count property. But the generic equivalent, IEnumerable(T), has a Count property.
The obvious solution is to use IEnumerable(T), but if you can't, you could do something like this:
_myList.Cast<MyListItemType>().Count()
The cast is an easy way to convert a IEnumerable to an IEnumerable(SomeType) but obviously is not the best way to get the count performance-wise.
If performance is a factor, I'd just loop through the values to get the count, unless you know the underlying collection has a Count property (see Jon Skeet's answer...).
If you include the System.Linq namespace, IEnumerable<T> has a Count() extension method available. You can write your own extension method to get it on the non-generic version. Note this method will box value types, so if that might end up being a performance concern for you, go with Jon Skeet's solution. This is just simpler.
public static int Count(this IEnumerable enumerable)
{
int count = 0;
foreach(object item in enumerable)
{
count++;
}
return count;
}
What about calling .ToList()?
If the underlying object implements ICollection, then you can use the .Count() property.
I needed the same and I created IEnumerableList. The reason was that I didnt like to evaluate every time I need the count through whole enumerable object as it's done with the extension method Count().
More about it here: http://fknet.wordpress.com/2010/08/11/string-formatwith-extension/
What's the "best" (taking both speed and readability into account) way to determine if a list is empty? Even if the list is of type IEnumerable<T> and doesn't have a Count property.
Right now I'm tossing up between this:
if (myList.Count() == 0) { ... }
and this:
if (!myList.Any()) { ... }
My guess is that the second option is faster, since it'll come back with a result as soon as it sees the first item, whereas the second option (for an IEnumerable) will need to visit every item to return the count.
That being said, does the second option look as readable to you? Which would you prefer? Or can you think of a better way to test for an empty list?
Edit #lassevk's response seems to be the most logical, coupled with a bit of runtime checking to use a cached count if possible, like this:
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list is ICollection<T>) return ((ICollection<T>)list).Count == 0;
return !list.Any();
}
You could do this:
public static Boolean IsEmpty<T>(this IEnumerable<T> source)
{
if (source == null)
return true; // or throw an exception
return !source.Any();
}
Edit: Note that simply using the .Count method will be fast if the underlying source actually has a fast Count property. A valid optimization above would be to detect a few base types and simply use the .Count property of those, instead of the .Any() approach, but then fall back to .Any() if no guarantee can be made.
I would make one small addition to the code you seem to have settled on: check also for ICollection, as this is implemented even by some non-obsolete generic classes as well (i.e., Queue<T> and Stack<T>). I would also use as instead of is as it's more idiomatic and has been shown to be faster.
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list == null)
{
throw new ArgumentNullException("list");
}
var genericCollection = list as ICollection<T>;
if (genericCollection != null)
{
return genericCollection.Count == 0;
}
var nonGenericCollection = list as ICollection;
if (nonGenericCollection != null)
{
return nonGenericCollection.Count == 0;
}
return !list.Any();
}
LINQ itself must be doing some serious optimization around the Count() method somehow.
Does this surprise you? I imagine that for IList implementations, Count simply reads the number of elements directly while Any has to query the IEnumerable.GetEnumerator method, create an instance and call MoveNext at least once.
/EDIT #Matt:
I can only assume that the Count() extension method for IEnumerable is doing something like this:
Yes, of course it does. This is what I meant. Actually, it uses ICollection instead of IList but the result is the same.
I just wrote up a quick test, try this:
IEnumerable<Object> myList = new List<Object>();
Stopwatch watch = new Stopwatch();
int x;
watch.Start();
for (var i = 0; i <= 1000000; i++)
{
if (myList.Count() == 0) x = i;
}
watch.Stop();
Stopwatch watch2 = new Stopwatch();
watch2.Start();
for (var i = 0; i <= 1000000; i++)
{
if (!myList.Any()) x = i;
}
watch2.Stop();
Console.WriteLine("myList.Count() = " + watch.ElapsedMilliseconds.ToString());
Console.WriteLine("myList.Any() = " + watch2.ElapsedMilliseconds.ToString());
Console.ReadLine();
The second is almost three times slower :)
Trying the stopwatch test again with a Stack or array or other scenarios it really depends on the type of list it seems - because they prove Count to be slower.
So I guess it depends on the type of list you're using!
(Just to point out, I put 2000+ objects in the List and count was still faster, opposite with other types)
List.Count is O(1) according to Microsoft's documentation:
http://msdn.microsoft.com/en-us/library/27b47ht3.aspx
so just use List.Count == 0 it's much faster than a query
This is because it has a data member called Count which is updated any time something is added or removed from the list, so when you call List.Count it doesn't have to iterate through every element to get it, it just returns the data member.
The second option is much quicker if you have multiple items.
Any() returns as soon as 1 item is found.
Count() has to keep going through the entire list.
For instance suppose the enumeration had 1000 items.
Any() would check the first one, then return true.
Count() would return 1000 after traversing the entire enumeration.
This is potentially worse if you use one of the predicate overrides - Count() still has to check every single item, even it there is only one match.
You get used to using the Any one - it does make sense and is readable.
One caveat - if you have a List, rather than just an IEnumerable then use that list's Count property.
#Konrad what surprises me is that in my tests, I'm passing the list into a method that accepts IEnumerable<T>, so the runtime can't optimize it by calling the Count() extension method for IList<T>.
I can only assume that the Count() extension method for IEnumerable is doing something like this:
public static int Count<T>(this IEnumerable<T> list)
{
if (list is IList<T>) return ((IList<T>)list).Count;
int i = 0;
foreach (var t in list) i++;
return i;
}
... in other words, a bit of runtime optimization for the special case of IList<T>.
/EDIT #Konrad +1 mate - you're right about it more likely being on ICollection<T>.
Ok, so what about this one?
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
return !enumerable.GetEnumerator().MoveNext();
}
EDIT: I've just realized that someone has sketched this solution already. It was mentioned that the Any() method will do this, but why not do it yourself? Regards
Another idea:
if(enumerable.FirstOrDefault() != null)
However I like the Any() approach more.
This was critical to get this to work with Entity Framework:
var genericCollection = list as ICollection<T>;
if (genericCollection != null)
{
//your code
}
If I check with Count() Linq executes a "SELECT COUNT(*).." in the database, but I need to check if the results contains data, I resolved to introducing FirstOrDefault() instead of Count();
Before
var cfop = from tabelaCFOPs in ERPDAOManager.GetTable<TabelaCFOPs>()
if (cfop.Count() > 0)
{
var itemCfop = cfop.First();
//....
}
After
var cfop = from tabelaCFOPs in ERPDAOManager.GetTable<TabelaCFOPs>()
var itemCfop = cfop.FirstOrDefault();
if (itemCfop != null)
{
//....
}
private bool NullTest<T>(T[] list, string attribute)
{
bool status = false;
if (list != null)
{
int flag = 0;
var property = GetProperty(list.FirstOrDefault(), attribute);
foreach (T obj in list)
{
if (property.GetValue(obj, null) == null)
flag++;
}
status = flag == 0 ? true : false;
}
return status;
}
public PropertyInfo GetProperty<T>(T obj, string str)
{
Expression<Func<T, string, PropertyInfo>> GetProperty = (TypeObj, Column) => TypeObj.GetType().GetProperty(TypeObj
.GetType().GetProperties().ToList()
.Find(property => property.Name
.ToLower() == Column
.ToLower()).Name.ToString());
return GetProperty.Compile()(obj, str);
}
Here's my implementation of Dan Tao's answer, allowing for a predicate:
public static bool IsEmpty<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null) throw new ArgumentNullException();
if (IsCollectionAndEmpty(source)) return true;
return !source.Any(predicate);
}
public static bool IsEmpty<TSource>(this IEnumerable<TSource> source)
{
if (source == null) throw new ArgumentNullException();
if (IsCollectionAndEmpty(source)) return true;
return !source.Any();
}
private static bool IsCollectionAndEmpty<TSource>(IEnumerable<TSource> source)
{
var genericCollection = source as ICollection<TSource>;
if (genericCollection != null) return genericCollection.Count == 0;
var nonGenericCollection = source as ICollection;
if (nonGenericCollection != null) return nonGenericCollection.Count == 0;
return false;
}
List<T> li = new List<T>();
(li.First().DefaultValue.HasValue) ? string.Format("{0:yyyy/MM/dd}", sender.First().DefaultValue.Value) : string.Empty;
myList.ToList().Count == 0. That's all
This extension method works for me:
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
try
{
enumerable.First();
return false;
}
catch (InvalidOperationException)
{
return true;
}
}