有时 Visual Studio IDE0032 推荐是错误的应用吗?

Vev*_*rke 3 c# refactoring code-analysis visual-studio roslyn-code-analysis

Visual Studio 2019给出了以下关于 private 的建议_myNum:改为使用auto-property。起初我很想这样做,摆脱这个private变量并拥有带有private set. 但这并没有提供相同的功能:我想要一个公共属性来公开这条给定的信息,并且只在一个可以设置这条数据的地方 - 构造函数,因此是关键字readonly

换句话说,我是对的吗?这个建议并不总是正确的?

public class Foo
{
    public int MyNum { get { return _myNum; } }
    private readonly int _myNum;
    public Foo(int num)
    {
        _myNum = num;
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

应用自动完成建议,代码如下所示:

public int MyNum { get; }

public Foo(int num)
{
    MyNum = num;
}
Run Code Online (Sandbox Code Playgroud)

小智 5

Visual Studio 建议您使用只读属性来简化和/或改进基于某些算法编写的代码,这些算法考虑不同的常见和标准编码技术来创建干净、简化、健壮和优化的代码。

这里的目标是替换在不执行任何其他操作的情况下获取私有字段值的只读属性和该私有字段。

因此,如果您接受此案例列表中的相关建议(我在 VS2017 中有几个),如果您在建议选项中选择“使用自动属性”进行更改,您将获得自动简化的书面代码代码(其他当然不相关):

public class Foo
{
  public int MyNum { get; }
  public Foo (int num)
  {
    MyNum = num;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是正确的建议,接受是合适的。

其他人的建议会产生您在大多数情况下不需要的东西......

如果您计划在 getter 中添加行为,则可以忽略 Visual Studio 的此建议:

public class Foo
{
  public int MyNum
  {
    get
    {
      return _myNum >= 100 ? 100 : _myNum;
    }
  }
  private readonly int _myNum;
  public Foo(int num)
  {
    _myNum = num;
  }
}
Run Code Online (Sandbox Code Playgroud)

否则,如果您想要只读数据成员,则可以使用只读字段:

public class Foo
{
  public readonly int MyNum;
  public Foo (int num)
  {
    MyNum = num;
  }
}
Run Code Online (Sandbox Code Playgroud)

C# 只读与 Get

只读字段与只读属性

只读修饰符和私有 setter 哪个更好?

字段和属性有什么区别?

但是,如果您需要此数据成员作为属性,例如用于序列化或由 Visual Studio 设计器和助手使用,并且它通常必须是可写的......并且如果您使用 C# 9+,则可以使用init - 唯一属性:

public class Foo
{
  public int MyNum { get; init; }
  public Foo (int num)
  {
    MyNum = num;
  }
}
Run Code Online (Sandbox Code Playgroud)

C# 9 中的 Init-Only 和 ReadOnly 有什么区别?

另外,在 C# 9 之前,没有 get-only 自动属性,要拥有与私有字段耦合的属性,并删除 Visual Studio 重构助手建议,无需禁用此模块,您可以简单地使用经典的 getter 方法来避免Visual Studio代码重构建议:

public class Foo
{
  private readonly int _myNum;
  public int GetMyNum() => _myNum;
  public Foo(int num)
  {
    _myNum = num;
  }
}
Run Code Online (Sandbox Code Playgroud)