views:

4457

answers:

9

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?

+17  A: 

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: if(item.IsNullOrValue(0)){} // but you don't get much from it

eglasius
Thing of beauty.
Patrick
thank you - very succinct! i was concerned with the readability, but came to the conclusion that it would be perfectly readable had I actually understood the ?? operator.
nailitdown
You should use the extension method; while it is readable at the moment of writing, this little code nuggets requires a fraction of thought, meaning if you try to read code and it uses it - you are distracted from your main problem.
configurator
@configurator: as it stands, i'd need an extension method for each nullable property of Item - that doesn't seem like the best solution
nailitdown
@nailitdown That was a quick extension method that works, but you can expand on it using generic ... personally I stick to the operator, because it is also supported on linq2sql :)
eglasius
@nailitdown: not really, you just need an extension method for Nullable<T>. double? is an alias for Nullable<double>. Your signature will look like: public static bool IsNullOrValue<T>(this Nullable<T>, t valueToCheck) where T : struct
Josh
@nailitdown: (part II) Your return statement would then look likereturn (value ?? default(T)).Equals(valueToCheck);
Josh
A: 
public static bool nz(object obj)
{
    return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}
Reflection is *slow*, be careful with solutions like this. I don't object to reflection, but I wouldn't expect it in a "simple" function like this and it would catch me off guard.
WaldenL
does this actually check for zero?
nailitdown
Actually, no. Activator.CreateInstance(obj.GetType()) will return null for nullable types, I believe.
configurator
@configurator: when nullable types are boxed, they're boxed as the underlying struct, i.e., so this will not construct a null-values nullable, but a default-valued non-nullable struct.
Eamon Nerbonne
+2  A: 

I agree with using the ?? operator.

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

Nick Josevski
+2  A: 

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.

WaldenL
cheers for catching that bug - in this project i need to check against int?, double?, decimal?, etc. which is why i'm using "object"
nailitdown
Remember, the '?' is just compiler sugar for the INullable<T> type, so you could probably take an INullable<T> as the parm and then jsut compare it to null (parm == null) and if not null compare to zero.
WaldenL
A: 
class Item{  
 bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}
dtroy
your solution works for one property, i should've specified i have many properties of the same item to check for null/zero
nailitdown
+7  A: 

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...

CMS
A: 

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 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) { }
    }
}
Sung Meister
i think you're right that eliminating null values at some earlier stage would've been the way to go
nailitdown
Not exactly. There is a concept called "Refactoring". You can refactor your code toward a better pattern or to a better structure. You can always *eliminate* nullable values at later stages.
Sung Meister
A: 

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

String.IsNullOrEmpty(str)

Instead of:

str==null || str==""

Chris
Question compares against "0" not an empty string.
Sung Meister
+2  A: 

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
Josh