我在一个类中有n个字段。最多允许设置其中一个,因此如果不是这种情况,我需要抛出一个例外。我知道 n 的值。
我可以用显而易见的方式做到这一点:
if (field1 != null && (field2 != null || field3 != null ||...)
|| field2 != null && (field1 != null || field3 != null ||...)
...)
throw new Exception();
然而,这个长度在字段数量中是 n^2,我绝对不想写出来,例如 10 个字段。
我看到过建议通过反思来做到这一点的建议。然而,虽然当你不知道n的值时,这是必要的,但我忍不住认为这里一定有一种更简单的方法。
那么有没有办法检查n个值中是否最多有一个不为空,而每个值只访问一次?
您可以有一个计数器来表示设置了多少个字段。
int numberOfSetFields = 0;
if (field1 != null)
numberOfSetFields++;
if (field2 != null)
numberOfSetFields++;
if (field3 != null)
numberOfSetFields++;
...
if (numberOfSetFields > 1)
{
throw new Exception();
}
或者,您可以使用属性,以便在至少设置了 1 个以上时不再检查其他字段
int numberOfSetFields = 0;
int NumberOfSetFields
{
get { return numberOfSetFields; }
set
{
numberOfSetFields = value;
if (numberOfSetFields > 1)
throw new Exception();
}
}
if (field1 != null)
NumberOfSetFields++;
if (field2 != null)
NumberOfSetFields++;
if (field3 != null)
NumberOfSetFields++;
...
属性的 NumberOfSetFields 的 set 方法将检查是否至少有 1 个设置字段。这样,假设您有 10 个字段,并且设置了前 2 个字段,那么与我提到的第一种方法相比,将不再检查其他 8 个字段。
可以使用带有描述性名称的帮助程序方法,使调用端更清楚地了解要检查的内容,如下所示:
public static bool MoreThanOneNotNull<T>(params T[] items)
{
int count = 0;
for (int i = 0; i < items.Length; i++)
if (items[i] is object && ++count > 1)
return true;
return false;
}
用法:
if (MoreThanOneNotNull(field1, field2, field3, field4, ... ))
// ...
public int NotNullToOne<T>(T val) => val is null ? 0 : 1;
if (NotNullToOne(field1) + NotNullToOne(field2) + NotNullToOne(field3) + ... > 1)
throw new Exception();
如果值不为空,则返回 1,如果是,则返回 o。
如果多个值为 null,则所有NotNullToOne
的总和将大于 1,因此将抛出该值。