繁体   English   中英

检查三个具有某些值的属性或它们在C#中全部为NULL的更好方法

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

对象中有三个属性

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

而且我需要验证所有三个属性都应包含某个值,或者所有三个属性都为空。

这是验证

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

还有其他更好的方法可以通过其他逻辑运算符来实现吗?

你可以试试这个

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

上面的表达式产生:

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

您可以对null检查使用null合并,但是您仍然需要验证所有项目是否确实具有另一个项目的值:

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

但是,我认为普通用户更容易理解原始的方式。

我不知道可以使代码看起来更好的逻辑运算符,但是我经常做的就是将功能包装到一个描述测试的名称的方法中。 这有助于减小代码大小,并使代码“自我记录”。

这是一个示例方法,它将测试一堆对象以查看它们是否“部分为空”。

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;
}

而这种方法正在起作用: 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;
    }
}

实际上,有几种方法可以解决此问题,具体取决于您在为对象添加新属性时希望它的“自动”程度。 如果您不介意每次添加新属性时都更新支票,那么我将使用一种简单的比较方法。

首先,您提供的示例是一种很好的方法。 实际上,这将是执行检查的最有效方式。 缺点是它过于冗长,如果计划向该对象添加更多属性,则扩展性不好。

您可以考虑的下一个方法是创建一个自定义函数,为您比较属性。 这样,当您在代码中使用该函数时,它就不再那么冗长。 下面的函数需要多少个int? 您想扔给它的变量,并验证它们是否都具有值或没有值。

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;
}

我建议的最后一个选择是使用反射。 通过反射,您可以遍历属性并使用与上述函数类似的逻辑来检查每个属性。 这种方法的好处是您在添加新属性时无需调整逻辑。 缺点是性能。

如果您只是要确保所有三个值都有或没有值(不管值是什么),则

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM