为什么 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))
为什么会显示这个警告?后代数量未知,因此循环数量未知。每个循环都可以将 hasStaticUsage
或 hasInstanceUsage
设置为 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
为假。
无论如何hasStaticUsage
和hasInstanceUsage
不能同时为真。
你可以通过为这个表达式创造真理来找到答案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
,这不可能。
我有以下代码,它会告诉我是否在代码的其他地方使用了某个 属性。这背后的想法是验证 属性 和 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))
为什么会显示这个警告?后代数量未知,因此循环数量未知。每个循环都可以将 hasStaticUsage
或 hasInstanceUsage
设置为 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
为假。
无论如何hasStaticUsage
和hasInstanceUsage
不能同时为真。
你可以通过为这个表达式创造真理来找到答案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
,这不可能。