为什么 ReSharper 告诉我这个表达式总是正确的?

Why does ReSharper tell me this expression is always true?

我有以下代码,它会告诉我是否在代码的其他地方使用了某个 属性。这背后的想法是验证 属性 和 private setter 是否可以设为只读。

这里有多个问题,但主要问题是在构造函数外部对 属性 的赋值意味着它不会触发。此外,静态 属性 可能只在静态构造函数中有一个赋值来触发诊断。同样,实例 属性 只需要一个实例构造函数。

现在,到目前为止,我遇到的大多数情况都已解决,但 ReSharper 在这段代码中给了我一个警告,我似乎无法弄清楚它的逻辑。上面的规范翻译成这段代码:

var isStaticProperty = propertySymbol.IsStatic;
bool hasInstanceUsage = false;
bool hasStaticUsage = false;

foreach (var identifier in outerClass.DescendantNodes().OfType<IdentifierNameSyntax>())
{
   var memberSymbol = context.SemanticModel.GetSymbolInfo(identifier);
   if (memberSymbol.Symbol.Equals(propertySymbol))
   {
       var constructor = identifier.Ancestors().OfType<ConstructorDeclarationSyntax>()
                                               .FirstOrDefault();
       var isInConstructor = constructor != null;
       var isAssignmentExpression = identifier.Ancestors()
                                               .OfType<AssignmentExpressionSyntax>()
                                               .FirstOrDefault() != null;

       // Skip anything that isn't a setter
       if (!isAssignmentExpression)
       {
           continue;
       }

       // if it is a setter but outside the constructor, we don't report any diagnostic
       if (!isInConstructor)
       {
           return;
       }

       var isStaticConstructor = context.SemanticModel
                                        .GetDeclaredSymbol(constructor).IsStatic;
       if (isStaticConstructor && isStaticProperty)
       {
           hasStaticUsage = true;
       }

       if (!isStaticConstructor && !isStaticProperty)
       {
           hasInstanceUsage = true;
       }
   }
}

// We can't set it to readonly if it's set in both the instance 
//   and the static constructor
// We need a NAND operation: either it's never set, 
//   it's set in ctor 1 or it's set in ctor 2
if (!(hasStaticUsage & hasInstanceUsage))
{
   context.ReportDiagnostic(Diagnostic.Create(
                 Rule, property.Identifier.GetLocation(), propertySymbol.Name));
}

随着警告

Expression is always true

上线

if (!(hasStaticUsage & hasInstanceUsage))

为什么会显示这个警告?后代数量未知,因此循环数量未知。每个循环都可以将 hasStaticUsagehasInstanceUsage 设置为 true,这意味着在 2 个循环之后(最早),两个值都可能变为 true 并且 if 条件应该失败:一个 NAND returns true, true, true, false.

这是我打算完成的布尔逻辑:

+----------------+------------------+--------+
| hasStaticUsage | hasInstanceUsage | result |
+----------------+------------------+--------+
| false          | false            | true   |
| false          | true             | true   |
| true           | false            | true   |
| true           | true             | false  |
+----------------+------------------+--------+

此块使您不可能将这两个变量都设置为 true:

if (isStaticConstructor && isStaticProperty)
{
     hasStaticUsage = true;
}

if (!isStaticConstructor && !isStaticProperty)
{
    hasInstanceUsage = true;
}

只能将其中一个变量设置为 true。所以你的 if 语句将永远等同于 !false == true.

isStaticProperty在循环外初始化:

var isStaticProperty = propertySymbol.IsStatic;

如果isStaticProperty为假,那么这个表达式:

 (isStaticConstructor && isStaticProperty)

始终为假,因此 hasStaticUsage 为假。

如果isStaticProperty为真,那么这个表达式:

 (!isStaticConstructor && !isStaticProperty)

始终为假,因此 hasInstanceUsage 为假。

无论如何hasStaticUsagehasInstanceUsage不能同时为真。

你可以通过为这个表达式创造真理来找到答案table。 isStaticConstructor && isStaticProperty!isStaticConstructor && !isStaticProperty。让我们一起来吧。

isStaticConstructor && isStaticProperty

+---------------------+------------------+--------+
| isStaticConstructor | isStaticProperty | result |
+---------------------+------------------+--------+
| false               | false            | false  |
| false               | true             | false  |
| true                | false            | false  |
| true                | true             | true   |
+---------------------+------------------+--------+

!isStaticConstructor && !isStaticProperty

+---------------------+------------------+--------+
| isStaticConstructor | isStaticProperty | result |
+---------------------+------------------+--------+
| false               | false            | true   |
| false               | true             | false  |
| true                | false            | false  |
| true                | true             | false  |
+---------------------+------------------+--------+

所以你可以看到, isStaticConstructor && isStaticProperty!isStaticConstructor && !isStaticProperty 都不可能是 true.

因此,根据您提供的事实 table,!(hasStaticUsage & hasInstanceUsage) 变为 false 的唯一可能性是两个表达式同时为 true,这不可能。