我有以下代码,它会告诉我代码中的其他地方是否使用了某个属性。这背后的想法是验证具有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));
}
警告
表达始终是真的
就行了
if (!(hasStaticUsage & hasInstanceUsage))
为什么会显示此警告?有一个未知数量的后代,所以有不明数量的循环。每个循环可以将hasStaticUsage
或hasInstanceUsage
设置为true
,这意味着在2个循环(最早)之后,两个值都可能变为true
,if条件将失败: NAND返回true
,true
,true
,false
。
这是我打算完成的布尔逻辑:
+----------------+------------------+--------+
| hasStaticUsage | hasInstanceUsage | result |
+----------------+------------------+--------+
| false | false | true |
| false | true | true |
| true | false | true |
| true | true | false |
+----------------+------------------+--------+
答案 0 :(得分:25)
isStaticProperty
在循环之外初始化:
var isStaticProperty = propertySymbol.IsStatic;
如果isStaticProperty
为false,则表达式为:
(isStaticConstructor && isStaticProperty)
始终为false,因此hasStaticUsage
为false。
如果isStaticProperty
为真,那么这个表达式为:
(!isStaticConstructor && !isStaticProperty)
始终为false,因此hasInstanceUsage
为false。
在任何情况下,hasStaticUsage
和hasInstanceUsage
都不能同时为真。
答案 1 :(得分:14)
您可以通过为此表达式创建真值表来找到答案。
isStaticConstructor && isStaticProperty
和!isStaticConstructor && !isStaticProperty
。让我们一起做。
isStaticConstructor&amp;&amp; isStaticProperty 强>
+---------------------+------------------+--------+
| isStaticConstructor | isStaticProperty | result |
+---------------------+------------------+--------+
| false | false | false |
| false | true | false |
| true | false | false |
| true | true | true |
+---------------------+------------------+--------+
!isStaticConstructor&amp;&amp; !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
,这是不可能的。
答案 2 :(得分:10)
此块使您无法将这两个变量都设置为true
:
if (isStaticConstructor && isStaticProperty)
{
hasStaticUsage = true;
}
if (!isStaticConstructor && !isStaticProperty)
{
hasInstanceUsage = true;
}
只能将其中一个变量设置为true
。因此,您的if
语句将始终相当于!false == true
。