-1

i have the following code in C#:

 if (this.Trucks.Any() || this.Cars.Any())
 {
      return true;
 }
 return false;

but i just realized that sometimes one or either of these arrays is null so in my case i wan null to just return false (instead of throwing exception).

I could add upfront null checks like this:

 if ((this.Trucks != null && this.Trucks.Any()) || 
    (this.Cars != null && this.Cars.Any()))
 {
    return true;
 }
  return false;
 }

but wanted to see if there was a cleaner way

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
leora
  • 188,729
  • 360
  • 878
  • 1,366
  • Make an extension method that returns false if the item is empty or null http://stackoverflow.com/questions/14565881/is-null-this-an-acceptable-use-of-extension-methods – GraemeMiller Jun 25 '14 at 21:12
  • Have you thought about catching the exception thrown? – DotN3TDev Jun 25 '14 at 21:13
  • 7
    [**!!!!Collections Should Never Be Null!!!!**](http://stackoverflow.com/a/1970001/643085). I can't stress this enough. Set `this.Trucks` and `this.Cars = new List()` in the constructor or something. – Federico Berasategui Jun 25 '14 at 21:16
  • Migrate from C# to F# – AK_ Jun 25 '14 at 21:19
  • 6
    And please just return the result of the boolean expression instead of true/false. – Brian Rasmussen Jun 25 '14 at 21:21
  • I usually use coalesce operator `(this.Trucks ?? new Truck[0]).Any()` or an extension method containing it (see `EmptyIfNull` answer) – digEmAll Jun 25 '14 at 21:34
  • @HighCore: that's definitely true. But sometimes you are forced to use old or bad written API that you can't change and that work with nulls :( – digEmAll Jun 25 '14 at 21:37
  • Take a look at this: http://stackoverflow.com/questions/10815641/elegant-way-to-avoid-nullreferenceexception-in-c-sharp – AK_ Jun 25 '14 at 21:45
  • Extension methods should look and behave like instance methods because a compatible instance method might be added in the future. So, any extension method receiving a null reference should throw a `NullReferenceException`. – Paulo Morgado Jun 25 '14 at 23:35

4 Answers4

4

I would create an extension method if you want to trate a null sequence as an empty one:

public static class Seq
{
    public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> seq)
    {
        return seq ?? Enumerable.Empty<T>();
    }
}

return this.Trucks.EmptyIfNull().Any() || this.Cars.EmptyIfNull().Any()

If you don't like having an extension method handling null values you could remove the this modifier and use

return Seq.EmptyIfNull(this.Trucks).Any() || Seq.EmptyIfNull(this.Cars).Any()
Lee
  • 142,018
  • 20
  • 234
  • 287
  • 1
    The concept of a `null IEnumerable` is somewhat troubling and as you can see, difficult to deal with. I always try to return `Enumerable.Empty` instead of `null` when possible and this is a clean way of forcing that. This little extension method should be part of every developer's bag of tricks. – andleer Jun 25 '14 at 21:40
  • 1
    Extension methods should look and behave like instance methods because a compatible instance method might be added in the future. So, any extension method receiving a null reference should throw a `NullReferenceException`. – Paulo Morgado Jun 25 '14 at 23:38
  • 3
    @PauloMorgado - You couldn't add a compatible instance method in future - the entire point is to handle null so throwing an NRE defeats the point. – Lee Jun 26 '14 at 08:18
  • @AK_, I don't understand your comment. You can't call a method on an null instance and you should be able to in an extension method. – Paulo Morgado Jun 26 '14 at 12:19
  • @Lee, I can't add instance methods to `IEnumerable`, but Microsoft can. We are assuming `Trucks` is an `IEnumerable` but it could be a `IMyCollection` which means I could add instance methods to it. If you follow that golden rule, you won't be bitten by this in the future. – Paulo Morgado Jun 26 '14 at 12:23
  • 2
    @PauloMorgado - No-one can add an instance method which converts a null sequence to an empty one. – Lee Jun 26 '14 at 12:24
  • @Lee, who said someone could? I didn't! – Paulo Morgado Jun 26 '14 at 12:30
  • 1
    @PauloMorgado - You just said "I can't add instance methods to `IEnumerable`, but Microsoft can". Neither Microsoft nor anyone else could add anything to `IEnumerable` to do what this extension method does. Your entire argument was that this method could cause problems since "a compatible instance method might be added in the future", however no such instance method could be added. – Lee Jun 26 '14 at 12:34
  • By compatible I meant "same name and same arguments". And, by the way, if you own the code you can add any instance method you want. It's the user of the class that can't call instance methods on null instances. And the same should go for extension methods. Do you know any BCL extension method that allows to extend null instnaces? – Paulo Morgado Jun 26 '14 at 12:44
  • 1
    @PauloMorgado - Your first issue applies to any extension method and the spec defines what happens in that case. It seems your real objection is having an extension method which handles nulls, so I've updated the answer. – Lee Jun 26 '14 at 13:24
  • I don't have a personal issue with anything. I'm just pointing out that the intention behind the design of extension methods was for them to be used and behave as instance methods. That makes your `Seq.EmtyIfNull` method a wrong use of extension methods. Just make it a "normal" static method and use it like this: `Seq.EmptyIfNull(this.Trucks).Any()`. – Paulo Morgado Jun 26 '14 at 17:53
4

I'd suggest you to keep with non-null contracts (null object pattern) as much as possible. That mean you will initialize probably in constructor empty array ( Enumerable.Empty<T>() in case of IEnumerable - in case of array add .ToArray() ). The problem with null checking is that is usually spread and multiplied over code - complexity of code (and unit tests) unnecessarily grows. It is easier to forget check for null in x places than forgetting to initialize empty object in one place. You can also use Code contracts library to check your "contracts" on runtime. In fact inventor of "null" call it's the billion dollar mistake: "Null References: The Billion Dollar Mistake"

fex
  • 3,488
  • 5
  • 30
  • 46
2

Make your own implementation:

public static Class StaticHelpers
{
    public static bool AnyEx<T>(this IEnumerable<T> enumerable)
    {
        if (enumerable == null) return false;

        return enumerable.Any();
    }
}

Use it like this:

if (this.Trucks.AnyEx() || this.Cars.AnyEx())
{
    return true;
}
return false;
Nathan A
  • 11,059
  • 4
  • 47
  • 63
  • @AK_ You can make the argument that having `null` collections is a bad idea (and there have been some good comments on the matter), but don't call it an error. I'd argue that it's not. If you can't assume that collections are `null`, this is one way to solve that problem. – Nathan A Jun 25 '14 at 21:34
  • I'm not saying its an error, I'm saying you have taken something bad, and made it worse. – AK_ Jun 25 '14 at 21:41
  • Extension methods should look and behave like instance methods because a compatible instance method might be added in the future. So, any extension method receiving a null reference should throw a `NullReferenceException`. – Paulo Morgado Jun 25 '14 at 23:36
  • @PauloMorgado counter-point: `string.IsNullOrEmpty`. In general, I agree though. – Blorgbeard Jun 26 '14 at 02:47
  • `string.IsNullOrEmpty`. and `string.IsNullOrWhitespace` are not extension methods and are the right way to do it in this case also. – Paulo Morgado Jun 26 '14 at 06:53
1

How about you just check them in the main if condition:

if ((this.Trucks != null && this.Trucks.Any()) || 
    (this.Cars != null && this.Cars.Any()))
{
  return true;
}
return false;

This can be rewritten as one long line:

return ((this.Trucks != null && this.Trucks.Any()) || 
        (this.Cars != null && this.Cars.Any()));
Yaakov Ellis
  • 40,752
  • 27
  • 129
  • 174
  • this is what i have above. . i was just asking to see if there was something cleaner . . looks like extention method is probably the way to go – leora Jun 25 '14 at 21:17
  • Extension methods are a trade-off. More concise, "cleaner" code up front, but hides more of the logic of what you are doing. – Yaakov Ellis Jun 25 '14 at 21:20
  • I agree. I think this is the "cleanest" way to do it, apart from simply guaranteeing the collections are never null in the first place (eg `readonly` lists initialized in ctor). – Blorgbeard Jun 25 '14 at 21:22