C#中的Null-coalescing运算符和&&运算符

3
在下面这种情况下,是否可能同时使用任意方式运算符??&&?请注意HTML标签的保留。
bool? Any
{
   get
   {
      var any = this.ViewState["any"] as bool?;
      return any.HasValue ? any.Value && this.SomeBool : any;
   }
}

这意味着以下内容:
  • 如果any为空,则this.Any.HasValue返回false
  • 如果any有值,则它会考虑另一个布尔属性并返回该值,即Any && SomeBool

你为什么想要使用 ?? 运算符?是为了让代码更短吗? - H H
@Henk Holterman:是的。还有运算符使用的实践。 - abatishchev
7个回答

4
我想知道为什么迄今为止没有人提出这个建议:

bool? any = this.ViewState["any"] as bool?;
return any & this.SomeBool;

这将返回

  • 如果any为null,则无论this.SomeBool的值是什么,都会返回null
  • 如果anythis.SomeBool都为true,则返回true;并且
  • 如果any不为null,并且this.SomeBool为false,则返回false

代码看起来不错,但描述有误(你怎么能同时返回nullfalse呢?然而,根据你的规则,对于any == nullthis.SomeBool == false会发生这种情况。 - Ben Voigt
@Henk Holterman:为什么操作数是'bool''bool?'而不是'bool?''bool'?!左操作数明显是bool?类型,因为我声明为这样。 - dtb
1
@Henk Holterman:是的,但是我在将其复制到我的答案时犯了一个笔误 :-( 现在已经修正了。我的测试程序:bool? x = null; bool y = true; bool? z = x&y; - dtb
你的代码可以重写为:return this.ViewState["any"] as bool? & this.SomeBool;,对吗? - abatishchev
@abatishchev:我也是这样认为。可能需要一些'(/)'。 - dtb
3
重要提示:&& 是一个短路布尔运算符,但是按位运算符 &不会短路。因此,在上面的代码中,无论如何都会对 this.SomeBool 进行评估。因此,请注意,在使用 Nullable<bool> 时,这并不能完全替代正常情况下使用 && 的方式。 - Robert Paulson

4

既然你希望在源代码为空的情况下返回null,我认为使用??并不能使你的代码更短更清晰。


看来你是对的。运算符 ?? 是用于在任何情况下返回一个值。这正是我不需要的。 - abatishchev

3

这是您所指的吗?

bool? Any 
{ 
   get 
   { 
      return ((this.ViewState["any"] as bool?) ?? false) && this.SomeBool;
   } 
} 

我将返回值保留为bool?,但看起来可以更改为bool。

测试如下:

class Program
{
    private static readonly Dictionary<string, object> ViewState = new Dictionary<string, object>();
    private static bool SomeBool;

    static void Main(string[] args)
    {
        ViewState["any"] = (bool?)null; SomeBool = true; Console.WriteLine(Any);
        ViewState["any"] = (bool?)false; SomeBool = true; Console.WriteLine(Any);
        ViewState["any"] = (bool?)true; SomeBool = true; Console.WriteLine(Any);
        ViewState["any"] = (bool?)null; SomeBool = false; Console.WriteLine(Any);
        ViewState["any"] = (bool?)false; SomeBool = false; Console.WriteLine(Any);
        ViewState["any"] = (bool?)true; SomeBool = false; Console.WriteLine(Any);
        Console.ReadLine();
    }

    static bool? Any
    {
        get
        {
            return ((ViewState["any"] as bool?) ?? false) && SomeBool;
        }
    }
}

该函数返回

False
False
True
False
False
False

这里的行为和原始版本不完全相同,因为为了使测试用例1和4相同,应该返回null。但也许这种行为并不是必需的?


很遗憾,result as bool? 总是 HasValue = true。不是吗? - abatishchev
1
他希望如果任何一个为空并且另外两个条件为假,则返回null。因此,他希望有TRUE、FALSE和NULL。 - Armstrongest
Daniel,非常感谢你详细的回答!但不幸的是我们讨论不同的行为 - 我需要保持返回值为Nullable<bool>,所以检查HasValue才有意义。 - abatishchev
我理解并同意Henk的观点,即在保持行为不变的情况下,无法以更简洁/更清晰的方式使用 ?? 和 &&。 - Daniel Renshaw

3
Null Coalescing 操作符无法适用于您的方法逻辑结构。当然,您可以强制使用它,但这样会显得很丑,并且会让任何阅读代码的人感到困惑。
我发现原始代码难以阅读和理解,因此进行了重构,并删除了三元运算符以显示意图。
bool? any = this.ViewState["any"] as bool?;

if (any == null)
    return null;

return any.Value && this.SomeBool;

空值合并运算符只是一种简洁的写法,应该谨慎使用。

Person contact = Mother ?? Father ?? FirstSibling;

比起下面的写法,更能够表达意图,也更易于阅读和维护:

这种写法比以下写法更具表现力,更易读易懂且易于维护:

Person contact = Mother;
if (contact == null)
    contact = Father;
if (contact == null)
    contact = FirstSibling;

2
我认为你想做的是这样的:

我认为您想做的是这个:

return any ?? (any.Value && this.SomeBool) ? true : new Nullable<bool>();

然而,在这种情况下,我认为更清晰的做法是使用if块:
if ( !any.HasValue )
  return (any.Value && this.SomeBool) ? true : any;
else 
  return any;

如果任何一个是null,那么你想返回truenull,对吧?

1

问题是,你实际上不想使用 ?? 运算符。它的作用是使避免空值变得容易,但你实际上想要保留空值。


-1
这段代码具有您所描述的行为: return (any ?? false) && this.SomeBool

和Daniel Renshaw的回答一样,你的答案也总是有值——要么是true,要么是false,从不是null - abatishchev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接