web-dev-qa-db-ja.com

ReSharperがこの表現が常に正しいと私に言うのはなぜですか?

特定のプロパティがコードの他の場所で使用されているかどうかを示す次のコードがあります。この背後にある考え方は、privateセッターを持つプロパティを読み取り専用にできるかどうかを確認することです。

ここには複数の落とし穴がありますが、主なものは、コンストラクターの外部のプロパティへの割り当ては、それが起動しないことを意味するということです。さらに、静的プロパティには、診断を起動するための静的コンストラクター内の割り当てのみが含まれる場合があります。同様に、インスタンスプロパティにはインスタンスコンストラクタのみが必要です。

さて、これまでのほとんどのシナリオが説明されていますが、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));
}

警告があります

式は常に真です

ライン上

if (!(hasStaticUsage & hasInstanceUsage))

なぜこの警告が表示されるのですか?子孫の数が不明であるため、ループの数が不明です。各ループはhasStaticUsageまたはhasInstanceUsagetrueに設定できます。つまり、2つのループの後(早くても)、両方の値がtrueになります。条件は失敗するはずです:NANDはtruetruetruefalseを返します。

これは、私が達成しようとしているブール論理です。

+----------------+------------------+--------+
| hasStaticUsage | hasInstanceUsage | result |
+----------------+------------------+--------+
| false          | false            | true   |
| false          | true             | true   |
| true           | false            | true   |
| true           | true             | false  |
+----------------+------------------+--------+
20
Jeroen Vannevel

isStaticPropertyはループの外側で初期化されます:

var isStaticProperty = propertySymbol.IsStatic;

isStaticPropertyがfalseの場合、次の式は次のとおりです。

 (isStaticConstructor && isStaticProperty)

は常にfalseであるため、hasStaticUsageはfalseです。

isStaticPropertyがtrueの場合、次の式は次のとおりです。

 (!isStaticConstructor && !isStaticProperty)

は常にfalseであるため、hasInstanceUsageはfalseです。

いずれにせよ、hasStaticUsagehasInstanceUsageの両方を同時に真にすることはできません。

25
default locale

この式の真理値表を作成することで、答えを見つけることができます。 _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になる可能性はないことがわかります。

したがって、提供した真理値表によっては、!(hasStaticUsage & hasInstanceUsage)falseになる唯一の可能性は、両方の式が同時にtrueである場合であり、これは不可能です。

14
Hamlet Hakobyan

このブロックにより、これらの変数の両方をtrueに設定することは不可能になります。

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

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

trueに設定できる変数は1つだけです。したがって、ifステートメントは常に!false == trueと同等になります。

10
Ed Cottrell