C# ReSharper:if/else if vs在C中切换#

C# ReSharper:if/else if vs在C中切换#,c#,refactoring,resharper,C#,Refactoring,Resharper,因此,我与一位同事讨论了ReSharper(目前为v8.1)在重构if/else if语句以切换语句方面的好处。我没怎么想,但我的同事想出了下面的例子。问题是,当代码运行时,您可以看到它实际上在DoElseIf中到达“else”语句,而不是在DoSwitch中。即使如此,ReSharper还是建议,当编译后的代码明显表现出不同的行为时,我将if/elseif重构为switch语句 任何比我更了解ReSharper的人能告诉我,我是否以错误的方式看待这个问题,或者我是否应该小心地将if/else

因此,我与一位同事讨论了ReSharper(目前为v8.1)在重构if/else if语句以切换语句方面的好处。我没怎么想,但我的同事想出了下面的例子。问题是,当代码运行时,您可以看到它实际上在DoElseIf中到达“else”语句,而不是在DoSwitch中。即使如此,ReSharper还是建议,当编译后的代码明显表现出不同的行为时,我将if/elseif重构为switch语句

任何比我更了解ReSharper的人能告诉我,我是否以错误的方式看待这个问题,或者我是否应该小心地将if/else if重构为switch语句

代码如下:

namespace ConsoleApplication1
{
   class Program
   {
          static bool MyValue { get; set; }
          static void Main(string[] args)
          {
                 Task t = new Task(ChangeIt);
                 t.Start();

                 for (var i = 0; i < 1000000; i++)
                 {
                       DoElseIf();
                 }
                 for (var i = 0; i < 1000000; i++)
                 {
                       DoSwitch();
                 }

                 Console.WriteLine("Work's done!");
                 Console.ReadLine();
          }

          static void DoSwitch()
          {
                 switch (MyValue)
                 {
                       case true:
                              //Console.WriteLine("true");
                              break;
                       case false:
                              //Console.WriteLine("false");
                              break;
                       default:
                              Console.WriteLine("WTF (Switch)!");
                              break;
                 }
          }

          static void DoElseIf()
          {
                 if (MyValue == true)
                 {
                       //Console.WriteLine("true");
                 }
                 else if (MyValue == false)
                 {
                       //Console.WriteLine("false");
                 }
                 else
                 {
                       Console.WriteLine("WTF (Else-if)!");
                 }
          }

          public static void ChangeIt()
          {
                 MyValue = !MyValue;
                 Task.Factory.StartNew(ChangeIt);
          }
   }
}
命名空间控制台应用程序1
{
班级计划
{
静态bool MyValue{get;set;}
静态void Main(字符串[]参数)
{
任务t=新任务(更改它);
t、 Start();
对于(变量i=0;i<1000000;i++)
{
DoElseIf();
}
对于(变量i=0;i<1000000;i++)
{
DoSwitch();
}
控制台。WriteLine(“工作完成了!”);
Console.ReadLine();
}
静态无效开关()
{
开关(MyValue)
{
大小写正确:
//Console.WriteLine(“真”);
打破
案例错误:
//控制台。写入线(“假”);
打破
违约:
控制台写入线(“WTF(开关)!”;
打破
}
}
静态void DoElseIf()
{
如果(MyValue==true)
{
//Console.WriteLine(“真”);
}
else if(MyValue==false)
{
//控制台。写入线(“假”);
}
其他的
{
Console.WriteLine(“WTF(Else if)!”);
}
}
公共静态void ChangeIt()
{
MyValue=!MyValue;
Task.Factory.StartNew(ChangeIt);
}
}
}
提前感谢并祝大家节日快乐:-)

R#是一个非常有用的工具,可以帮助您编写更好的代码。它从不破坏工作代码吗?不,这也是为什么没有“所有建议的重构”按钮的原因

更一般地回答你的问题:你应该始终了解代码的R#变化。你是程序员

PS:当你发现一个场景,其中R#破坏了工作代码,再看一看那段特定的代码,它可能已经是低质量的了


PPS:我使用R#已经很长时间了,从来没有遇到过R#建议实现bug的例子:)

您的例子是一个非常具体的例子,您在一个非线程安全的循环中运行if语句,这意味着您希望另一个任务在计算变量时更改它的值

通常,您希望防止此类情况,因为这可能会导致非常糟糕的问题

关于你的问题,ReSharper应该如何知道这个事实?通常,如果您执行if/elseif,我们可以期望语句得到正确的计算,对吗

此外,开关甚至可以帮助您防止这种混乱,因此在我看来,R#是正确的;)


但当然,如果不仔细检查这些建议,你就不能盲目相信R#。通常一些建议都是废话,您还必须配置R#以符合您的代码风格指南等。。。它只是一个工具;)

下面是Lasse的评论,下面是一个简短的例子:

class Program
{
    private static bool _pathological = true;
    private static bool Pathological
    {
        get
        {
            return (_pathological = !_pathological);
        }
    }

    static void Main(string[] args)
    {
        DoElseIf();
        DoSwitch();

        Console.WriteLine("Work's done!");
        Console.ReadLine();
    }

    static void DoSwitch()
    {
        switch (Pathological)
        {
            case true:
                //Console.WriteLine("true");
                break;
            case false:
                //Console.WriteLine("false");
                break;
            default:
                Console.WriteLine("WTF (Switch)!");
                break;
        }
    }

    static void DoElseIf()
    {
        // R# offers Convert to Switch on the below if, which results
        // in the code in DoSwitch, which has *different* behaviour
        if (Pathological == true)
        {
            //Console.WriteLine("true");
        }
        else if (Pathological == false)
        {
            //Console.WriteLine("false");
        }
        else
        {
            Console.WriteLine("WTF (Else-if)!");
        }
    }
}

我同意这是ReSharper中的一个bug;你应该把它交给警察局。ReSharper错误地假设属性的后续获取将返回相同的值。它还错误地为
volatile
字段提供了convert to switch,这也很糟糕。

明白了。我只是很惊讶,R#实际上暗示了一些东西,可能最终生成的代码会像预期的那样工作。老实说,你提供的例子有点疯狂。当另一个线程正在对该属性执行读取时,持续更新MyValue似乎是解决此类争用条件的一个很好的方法。switch语句从未处于该状态的唯一原因是,对属性只有一次检查,而使用if语句对属性进行两次检查。这与其说是R#提出的“奇怪的建议”,不如说是一个非常不确定的编程示例:)这里不需要引入线程,只要让属性在读取时返回相反的值即可。当使用Task修改值时,调用
DoelSif()在两个循环中,两个循环的结果将不相同,问题是您使用的是一个共享变量,
MyValue
,由两个线程访问。