【问题标题】:ReSharper can´t find unreachable codeReSharper 找不到无法访问的代码
【发布时间】:2016-09-29 05:52:27
【问题描述】:

我有这个代码:

Assert.IsTrue(datasetMetadata1 != null && datasetMetadata1.Length == 5);
Assert.IsTrue(datasetMetadata2 != null && datasetMetadata2 .Length == 11);

if ((datasetMetadata1 == null || datasetMetadata1.Length != 5) ||
(datasetMetadata2 == null || datasetMetadata2 .Length != 11)
{ 
    /* do something */ 
}

ReSharper 通过删除冗余(因为总是 true)表达式 == null 并将 if 语句反转为类似于以下内容来简化:

if ((datasetMetadataPunktort.Length == 5) && (datasetMetadataFlurstueck.Length == 11)) 
    return

但是对我来说,即使这个检查似乎也毫无意义,并且很容易被忽略,因为条件总是正确的。所以我想知道为什么 ReSharper 会检测到针对 null 的过时检查,而不是其余的。

我是否遗漏了任何检查失败的情况?

【问题讨论】:

  • Resharper 应该如何知道 Length 在运行时会有什么值?
  • @j0ey_wh 嗯,公平点。它无法知道属性是否不可变,这就是您的意思,不是吗?
  • 也许如果你引入一个长度的变量它会注意到吗?
  • @Euphoric 不,即使将 Length 存储到变量中并将其用于 Assert 和 if 语句 R# 也不会注意到它们是相等的条件。
  • 在我看来,事情是这样的:每次测试你的值时,你都会调用 getter。 Resharper 不知道您的实际 getter 是否修改了您的值。您第一次调用 getter 时可能会返回 5 并将值增加 6。所以下次您将返回 11。

标签: c# visual-studio-2010 resharper-2016


【解决方案1】:

除了 Visalievski 的回答,让我再添加一个更简单的例子:

int i = 5;
if (i != 5)
{
    // do something
}

使用此 sn-p,ReSharper 不会检测到无法访问的代码。

但让我对那段代码做一个小改动:让 i 保持不变。

const int i = 5;
if (i != 5)
{
    // do something
}

现在,ReSharper 抱怨代码无法访问,我在 VS2015 中收到编译器警告 CS0162。

因此,在处理特定值时,ReSharper 和编译器都会询问该值是否保证为常量。因此我得出结论,null 和特定值使用的启发式方法是不同的。

【讨论】:

    【解决方案2】:

    解释我的评论:

    在我看来,事情是这样的:每次你测试你的值时,你都会调用 getter。 Resharper 不知道您的实际 getter 是否修改了您的值。您第一次调用 getter 时可能会返回 5 并将值增加 6。所以下一次您将返回 11。

    我创建了这个小型控制台应用程序作为示例:

    这个类包含带有特殊getter的参数。

    public class TestClass
    {
        private int _length;
    
        public int Length
        {
            get
            {
                var localLength = _length;
                _length += 6;
                return localLength;
            }
            set { _length = value; }
        }
    
        public TestClass(int length)
        {
            this._length = length;
        }
    }
    

    这个类用于测试目的:

      class Program
    {
        static void Main(string[] args)
        {
            var testObject = new TestClass(5);
            if ((testObject.Length == 5) && (testObject.Length == 11))
            {
                Console.WriteLine("TRUE");
            }
            else
            {
                Console.WriteLine("FALSE");
            }
            Console.Read();
    
        }
    }
    

    我们有以下输出:

    TRUE
    

    我同意这个类是非常特殊的,并且是为了使条件起作用而制作的,但它仍然表明这种情况是可能的。

    总的来说,说明由于每个条件之间调用了getter,所以值是可以变化的,所以调用不是多余的。

    【讨论】:

      猜你喜欢
      • 2020-08-27
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多