2015-06-08 7 views
20

Ich habe den folgenden Code, der mir sagen wird, ob eine bestimmte Eigenschaft an anderer Stelle im Code verwendet wird. Die Idee dahinter ist zu überprüfen, ob eine Eigenschaft mit einem private Setter Readonly gemacht werden kann.Warum sagt mir ReSharper, dass dieser Ausdruck immer wahr ist?

Hier gibt es mehrere Fehler, aber die wichtigsten sind, dass eine Zuweisung zur Eigenschaft außerhalb des Konstruktors bedeutet, dass sie nicht ausgelöst wird. Darüber hinaus kann eine statische Eigenschaft nur eine Zuweisung in einem statischen Konstruktor haben, um die Diagnose auszulösen. Ebenso benötigt eine Instanzeigenschaft nur einen Instanzkonstruktor.

Jetzt sind die meisten Szenarien, die ich bis jetzt habe, noch berücksichtigt ReSharper gibt mir eine Warnung in diesem Stück Code und ich kann einfach nicht scheinen, seine Logik herauszufinden. Die obige Beschreibung ist in diesem Stück Code übersetzt:

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)); 
} 

Mit der Warnung

sein

Expression ist immer wahr

auf der Linie

if (!(hasStaticUsage & hasInstanceUsage)) 

Warum Es zeigt diese Warnung? Es gibt eine unbekannte Anzahl von Nachkommen, also gibt es eine unbekannte Menge an Schleifen. Jede Schleife kann hasStaticUsage oder hasInstanceUsage zu true gesetzt, was bedeutet, dass nach 2 Schlaufen (frühestens), beide Werte true werden könnten und die, wenn die Bedingung fehlschlagen sollte: ein NAND kehrt true, true, true, false.

Dies ist die Boolesche Logik Ich beabsichtige, zu erreichen:

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

Wo wird 'isStaticProperty' initialisiert? –

+0

Auf derselben Ebene von 'hasInstanceUsage'. Ich werde es der Vollständigkeit halber hinzufügen, aber ich glaube nicht, dass es Auswirkungen hat. –

+0

'Ich habe den folgenden Code, der mir sagen wird, ob eine bestimmte Eigenschaft an anderer Stelle im Code verwendet wird. - Ist das nicht eine native Funktion in VS? – Davor

Antwort

25

isStaticProperty ist außerhalb der Schleife initialisiert:

var isStaticProperty = propertySymbol.IsStatic; 

Wenn isStaticProperty falsch ist, dann ist dieser Ausdruck:

(isStaticConstructor && isStaticProperty) 

ist immer falsch, daher hasStaticUsage falsch ist.

Wenn isStaticProperty wahr ist, dann dieser Ausdruck:

(!isStaticConstructor && !isStaticProperty) 

ist immer falsch, also hasInstanceUsage falsch ist.

In jedem Fall hasStaticUsage und hasInstanceUsage können nicht beide gleichzeitig wahr sein.

10

Dieser Block macht es unmöglich, dass Sie jemals diese beiden Variablen true gesetzt werden: die Variablen

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

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

Nur einer von kann immer auf true gesetzt werden. Ihre if-Anweisung entspricht also immer !false == true.

+0

Die Warnung bleibt bestehen. –

+0

@JeroenVannevel siehe meine Bearbeitung. Sie haben ein logisches Problem an anderer Stelle im Code. –

+0

Es stellte sich tatsächlich heraus, dass 'iStaticProperty' boolean ist, was ich völlig übersehen habe. Ich schätze es, dass du mit mir suchst. –

14

Sie können die Antwort herausfinden, indem Sie eine Wahrheitstabelle für diese Ausdrücke erstellen. isStaticConstructor && isStaticProperty und !isStaticConstructor && !isStaticProperty. Machen wir es zusammen.

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 | 
+---------------------+------------------+--------+ 

So können Sie sehen, dass es keine jede Möglichkeit, dass die beiden isStaticConstructor && isStaticProperty und !isStaticConstructor && !isStaticProperty zu sein true.

Also, abhängig von der Wahrheitstabelle, die Sie angegeben haben, ist die einzige Möglichkeit, dass false wird, wenn beide Ausdrücke true in der gleichen Zeit sind, was unmöglich ist.

+0

Das war in der Tat die Ursache - ich habe gerade keine Verbindung mit 'isStaticProperty' hergestellt und vergessen, dass sie sich während der Zyklen nicht ändern konnte. –