Reputation: 1212
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
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
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
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
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
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