为什么ReSharper告诉我这个表达总是如此?

Jer*_*vel 20 c# resharper boolean-logic roslyn

我有以下代码,它将告诉我代码中的其他地方是否使用了某个属性.这背后的想法是验证具有privatesetter 的属性是否可以只读.

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

现在,到目前为止我已经考虑了大多数场景,但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));
}
Run Code Online (Sandbox Code Playgroud)

随着警告

表达总是如此

在线上

if (!(hasStaticUsage & hasInstanceUsage))
Run Code Online (Sandbox Code Playgroud)

为什么会显示此警告?有一个未知数量的后代,所以有一个未知数量的循环.每个环可以设置hasStaticUsagehasInstanceUsagetrue,这意味着后2个循环(在最早),这两个值可以成为true和如果条件应失败:一个NAND返回true,true,true,false.

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

+----------------+------------------+--------+
| hasStaticUsage | hasInstanceUsage | result |
+----------------+------------------+--------+
| false          | false            | true   |
| false          | true             | true   |
| true           | false            | true   |
| true           | true             | false  |
+----------------+------------------+--------+
Run Code Online (Sandbox Code Playgroud)

def*_*ale 25

isStaticProperty 在循环外初始化:

var isStaticProperty = propertySymbol.IsStatic;
Run Code Online (Sandbox Code Playgroud)

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

 (isStaticConstructor && isStaticProperty)
Run Code Online (Sandbox Code Playgroud)

总是假的,因此hasStaticUsage是假的.

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

 (!isStaticConstructor && !isStaticProperty)
Run Code Online (Sandbox Code Playgroud)

总是假的,因此hasInstanceUsage是假的.

在任何情况下hasStaticUsage,并hasInstanceUsage不能同时在同一时间是真实的.


Ham*_*yan 14

您可以通过为此表达式创建真值表来找到答案. isStaticConstructor && isStaticProperty!isStaticConstructor && !isStaticProperty.我们一起做吧.

isStaticConstructor && isStaticProperty

+---------------------+------------------+--------+
| isStaticConstructor | isStaticProperty | result |
+---------------------+------------------+--------+
| false               | false            | false  |
| false               | true             | false  |
| true                | false            | false  |
| true                | true             | true   |
+---------------------+------------------+--------+
Run Code Online (Sandbox Code Playgroud)

!isStaticConstructor &&!isStaticProperty

+---------------------+------------------+--------+
| isStaticConstructor | isStaticProperty | result |
+---------------------+------------------+--------+
| false               | false            | true   |
| false               | true             | false  |
| true                | false            | false  |
| true                | true             | false  |
+---------------------+------------------+--------+
Run Code Online (Sandbox Code Playgroud)

所以你可以看到,没有任何可能性都isStaticConstructor && isStaticProperty!isStaticConstructor && !isStaticPropertytrue.

因此,根据您已提供的真值表,那唯一的可能性!(hasStaticUsage & hasInstanceUsage)变得false是当两个表达式是true在同一时间,这是不可能的.


eli*_*ide 10

此块使您无法将这两个变量设置为true:

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

if (!isStaticConstructor && !isStaticProperty)
{
    hasInstanceUsage = true;
}
Run Code Online (Sandbox Code Playgroud)

只能将其中一个变量设置为true.所以你的if陈述总是等同于!false == true.