Manish Rawat
Manish Rawat

Reputation: 1212

Better way to check three properties having some value or all of them are NULL in C#

There are three properties in the object

{obj.prop1, obj.prop2, obj.prop3} These properties are NULLABLE INTEGER

And I need to validate either all three properties should contain some value or all three properties are null.

Here's the validation

if (!((!obj.prop1.HasValue && !obj.prop2.HasValue && !obj.prop3.HasValue) ||
                (obj.prop1.HasValue && obj.prop2.HasValue && obj.prop3.HasValue)))
{
     //throw new Exception("");
}

Is there any better way to do it via some other Logical operators?

Upvotes: 0

Views: 335

Answers (5)

Scott Hannen
Scott Hannen

Reputation: 29207

If you just want to make sure that all three have a value or don't have a value (regardless of what the value is) then

bool AllAreTrueOrFalse(params bool[] values)
{
    return values.All(value=>value) || !values.Any(value=>value);
}

var allTrueOrFalse = AllAreTrueOrFalse(obj.prop1.HasValue, obj.prop2.HasValue, 
    obj.prop3.HasValue);

Upvotes: 0

Zdeslav Vojkovic
Zdeslav Vojkovic

Reputation: 14581

You can try this

if (obj.prop1.HasValue != obj.prop2.HasValue || obj.prop2.HasValue != obj.prop3.HasValue) 
   throw...

The expression above yields:

p1.HasValue  p2.HasValue  p3.HasValue
==========================================================================
   false        false        false           => false || false => false
   false        false        true            => false || true  => true
   false        true         false           => true  || true  => true
   true         false        false           => true  || false => true
   false        true         true            => true  || false => true
   true         true         false           => false || true  => true
   true         false        true            => true  || true  => true
   true         true         true            => false || false => false

Upvotes: 4

gmiley
gmiley

Reputation: 6604

You could use null coalescing for the null check, but you would still need to verify if all items do actually have a value for the other:

if((obj.prop1 ?? obj.prop2 ?? obj.prop3) == null 
   || (obj.prop1.HasValue && obj.prop2.HasValue && obj.prop3.HasValue)) 
{
   // conditional block
}

However, I think the original way you have it is more understandable to an average user.

Upvotes: 1

Shawn Lehner
Shawn Lehner

Reputation: 1323

There are actually a handful of ways you can go about this depending on how "automatic" you want it to be when you add new properties for the object. If you don't mind updated your check each time you add a new property, I would just go with a simple method for comparison.

First, the example you have provided is a just fine approach. This is actually going to be the most performant way to perform the check. The downside is it is overly verbose, and doesn't scale well if you plan to add a lot more properties to the object.

The next method you could consider is to create a custom function that compares the properties for you. This way, when you use the function in your code, it is a bit less verbose. The function below will take as many int? variables you want to throw at it, and verify that they all either have a value, or don't have a value.

bool Test(params int?[] props) 
{
    bool? lastValue = null;
    foreach(int? p in props) 
    {
        // We haven't got a status yet so we just use the status for the first prop
        if (lastValue.HasValue == false)
            lastValue = p.HasValue;
        else
        {
            // If the status of this next prop doesn't match the first, we know it is false
            if (p.HasValue != lastValue.Value) 
                return false;
        }
    }

    // Default back to true since we didn't identify any issues.
    return true;
}

The last option I would propose would be to use reflection. With reflection, you could loop over the properties and check each one using similar logic to the function above. The benefit of this approach is that you do not need to adjust your logic as you add new properties. The downside is performance.

Upvotes: 0

user310988
user310988

Reputation:

I don't know of a logical operator that can make the code look nicer, but what I often do is wrap the functionality in to a method with a name that describes the test. This helps reduce the code size, and makes the code "self documenting".

Here's an example method that will test a bunch of objects to see if they are "partially null".

private static bool ArePartiallyNull(params object[] values)
{
    if(values.Length <= 1)
        return false;

    var isNull = values[0] == null;

    for(var i = 1;i < values.Length;i++)
    {
        if(isNull != (values[i] == null))
            return true;
    }

    return false;
}

And this method in action: https://dotnetfiddle.net/6QIpDF

public class Program
{
    public static void Main()
    {
        int? one = 1;
        int? two = 1;
        int? three = 1;

        int? nullOne = null;
        int? nullTwo = null;
        int? nullThree = null;

        Console.WriteLine(ArePartiallyNull(one, two, three));
        Console.WriteLine(ArePartiallyNull(nullOne, nullTwo, nullThree));
        Console.WriteLine(ArePartiallyNull(one, two, nullThree));
    }

    private static bool ArePartiallyNull(params object[] values)
    {
        if(values.Length <= 1)
            return false;

        var isNull = values[0] == null;

        for(var i = 1;i < values.Length;i++)
        {
            if(isNull != (values[i] == null))
                return true;
        }

        return false;
    }
}

Upvotes: 0

Related Questions