Nullable types: better way to check for null or zero in c#

C#NullZero

C# Problem Overview


I'm working on a project where i find i'm checking for the following in many, many places:

if(item.Rate == 0 || item.Rate == null) { }

more as a curiousity than anything, what's the best way to check for both cases?

I've added a helper method which is:

public static bool nz(object obj)
{
    var parsedInt = 0;
    var parsed = int.TryParse(obj.ToString(), out parsedInt);
    return IsNull(obj) || (parsed && parsedInt == 0);
}

Is there a better way?

C# Solutions


Solution 1 - C#

I like if ((item.Rate ?? 0) == 0) { }

Update 1:

You could also define an extension method like:

public static bool IsNullOrValue(this double? value, double valueToCheck)
{
    return (value??valueToCheck) == valueToCheck;
}

And use it like this:

if(item.IsNullOrValue(0)){} // but you don't get much from it

Solution 2 - C#

Although I quite like the accepted answer, I think that, for completeness, this option should be mentioned as well:

if (item.Rate.GetValueOrDefault() == 0) { }

This solution


¹ This should not influence your decision, though, since these kinds of micro-optimization are unlikely to make any difference.

Solution 3 - C#

Using generics:

static bool IsNullOrDefault<T>(T value)
{
    return object.Equals(value, default(T));
}

//...
double d = 0;
IsNullOrDefault(d); // true
MyClass c = null;
IsNullOrDefault(c); // true

If T it's a reference type, value will be compared with null ( default(T) ), otherwise, if T is a value type, let's say double, default(t) is 0d, for bool is false, for char is '\0' and so on...

Solution 4 - C#

This is really just an expansion of Freddy Rios' accepted answer only using Generics.

public static bool IsNullOrDefault<T>(this Nullable<T> value) where T : struct
{
	return default(T).Equals( value.GetValueOrDefault() );
}

public static bool IsValue<T>(this Nullable<T> value, T valueToCheck) where T : struct
{
	return valueToCheck.Equals((value ?? valueToCheck));
}

NOTE we don't need to check default(T) for null since we are dealing with either value types or structs! This also means we can safely assume T valueToCheck will not be null; Remember here that T? is shorthand Nullable<T> so by adding the extension to Nullable<T> we get the method in int?, double?, bool? etc.

Examples:

double? x = null;
x.IsNullOrDefault(); //true

int? y = 3;
y.IsNullOrDefault(); //false

bool? z = false;
z.IsNullOrDefault(); //true

Solution 5 - C#

C#9 : you can write

if (item.Rate is null or 0)

Solution 6 - C#

I agree with using the ?? operator.

If you're dealing with strings use if(String.IsNullOrEmpty(myStr))

Solution 7 - C#

You code sample will fail. If obj is null then the obj.ToString() will result in a null reference exception. I'd short cut the process and check for a null obj at the start of your helper function. As to your actual question, what's the type you're checking for null or zero? On String there's a great IsNullOrEmpty function, seems to me this would be a great use of extension methods to implement an IsNullOrZero method on the int? type.

Edit: Remember, the '?' is just compiler sugar for the INullable type, so you could probably take an INullable as the parm and then jsut compare it to null (parm == null) and if not null compare to zero.

Solution 8 - C#

> is there a better way?

Well, if you are really looking for a better way, you can probably add another layer of abstraction on top of Rate. Well here is something I just came up with using Nullable Design Pattern.

using System;
using System.Collections.Generic;

namespace NullObjectPatternTest { public class Program { public static void Main(string[] args) { var items = new List { new Item(RateFactory.Create(20)), new Item(RateFactory.Create(null)) };

        PrintPricesForItems(items);
    }

    private static void PrintPricesForItems(IEnumerable<Item> items)
    {
        foreach (var item in items)
            Console.WriteLine("Item Price: {0:C}", item.GetPrice());
    }
}

public abstract class ItemBase
{
    public abstract Rate Rate { get; }
    public int GetPrice()
    {
        // There is NO need to check if Rate == 0 or Rate == null
        return 1 * Rate.Value;
    }
}

public class Item : ItemBase
{
    private readonly Rate _Rate;
    public override Rate Rate { get { return _Rate; } }
    public Item(Rate rate) { _Rate = rate; }
}

public sealed class RateFactory
{
    public static Rate Create(int? rateValue)
    {
        if (!rateValue || rateValue == 0) 
            return new NullRate();
        return new Rate(rateValue);
    }
}

public class Rate
{
    public int Value { get; set; }
    public virtual bool HasValue { get { return (Value > 0); } }
    public Rate(int value) { Value = value; }
}

public class NullRate : Rate
{
    public override bool HasValue { get { return false; } }
    public NullRate() : base(0) { }
}

}

Solution 9 - C#

public static bool nz(object obj)
{
	return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}

Solution 10 - C#

class Item{  
 bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}

Solution 11 - C#

Don't forget, for strings, you can always use:

String.IsNullOrEmpty(str)

Instead of:

str==null || str==""

Solution 12 - C#

Using C# 7.0 or later you could use the is keyword to match objects against a pattern like this: (see is operator - C# reference | Microsoft)

if (item is { Rate: 0 or null })
{
  // Do something
}

Solution 13 - C#

One step further from Joshua Shannon's nice answer. Now with preventing boxing/unboxing:

public static class NullableEx
{
    public static bool IsNullOrDefault<T>(this T? value)
        where T : struct
    {
        return EqualityComparer<T>.Default.Equals(value.GetValueOrDefault(), default(T));
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnailitdownView Question on Stackoverflow
Solution 1 - C#eglasiusView Answer on Stackoverflow
Solution 2 - C#HeinziView Answer on Stackoverflow
Solution 3 - C#Christian C. SalvadóView Answer on Stackoverflow
Solution 4 - C#Joshua ShannonView Answer on Stackoverflow
Solution 5 - C#Eric Bole-FeysotView Answer on Stackoverflow
Solution 6 - C#Nick JosevskiView Answer on Stackoverflow
Solution 7 - C#Walden LeverichView Answer on Stackoverflow
Solution 8 - C#dance2dieView Answer on Stackoverflow
Solution 9 - C#SheaView Answer on Stackoverflow
Solution 10 - C#dtroyView Answer on Stackoverflow
Solution 11 - C#ChrisView Answer on Stackoverflow
Solution 12 - C#elillesaeterView Answer on Stackoverflow
Solution 13 - C#DeilanView Answer on Stackoverflow