3

Visual Studio 2019 gives the following recommendation on the private _myNum: to use auto-property instead. At first I was tempted to do so, getting rid of this private variable and having the property with a private set. But this does not give the same functionality: I want a public property to expose the this given piece of information, AND to one single place only where this piece of data can be set - the constructor, hence the readonly keyword.

In other words, am I right and this recommendation is not always correct ?

public class Foo
{
    public int MyNum { get { return _myNum; } }
    private readonly int _myNum;
    public Foo(int num)
    {
        _myNum = num;
    }
}

enter image description here

Applying the auto complete recommendation, the code looks like:

public int MyNum { get; }

public Foo(int num)
{
    MyNum = num;
}
Veverke
  • 9,208
  • 4
  • 51
  • 95
  • 3
    "having the property with a private set" - that's not part of the recommendation. It's recommending you declare it `{get;}` only. – Damien_The_Unbeliever Jan 25 '21 at 13:02
  • 2
    Take a look at the suggested code and make a decision. If it doesn't fit your use case then feel free to ignore the suggestion. It's up to you as the developer whether to follow the suggestion or not. – phuzi Jan 25 '21 at 13:02
  • 4
    [auto-implemented properties](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-implement-a-lightweight-class-with-auto-implemented-properties): "You can declare only the get accessor, which makes the property immutable everywhere except in the type's constructor." – Damien_The_Unbeliever Jan 25 '21 at 13:04
  • 1
    https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/init – Hans Passant Jan 25 '21 at 13:05
  • @mjwills: added that to the post – Veverke Jan 25 '21 at 13:38
  • In my opinion the correct answer here should be @HansPassant remark. The motif for posting this question was that I mistakenly thought that the only way to achieve immutable properties was with the `readonly` keyword. I did not think what happens with a `get` alone . @HansPassant, would you leave your bit as an answer so I accept it ? – Veverke Jan 25 '21 at 13:50

1 Answers1

5

Visual Studio recommends that you use a read-only property to simplify and/or improve the code written based on certain algorithms that takes in consideration different common and standard coding techniques to create clean, reduced, robust and optimized code.

Here, the goal is to replace both the read-only property that gets the value of the private field without doing anything else, and that private field.

So, if you accept the relevant suggestion in the list for this case (I have several with VS2017), you will get the written code automatically simplified for you in case you select the choice "Use auto-property" in the suggested options to change the code (others are certainly not relevant):

public class Foo
{
  public int MyNum { get; }
  public Foo (int num)
  {
    MyNum = num;
  }
}

This is a correct suggestion and accepting it is suitable.

Others suggestions produces things you will in most cases not need...

If you plan to add behaviors in the getter, you can ignore this suggestion from Visual Studio:

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

Otherwise if you want a read only data member, you can use a read-only field:

public class Foo
{
  public readonly int MyNum;
  public Foo (int num)
  {
    MyNum = num;
  }
}

C# readonly vs Get

Readonly field vs. readonly property

Which is better between a readonly modifier and a private setter?

What is the difference between a field and a property?

But if you need this data member being a property, for example to be used in serialization or by the Visual Studio Designers and Helpers, and it must be writable in general... and if you use C# 9+, you can use an init-only property:

public class Foo
{
  public int MyNum { get; init; }
  public Foo (int num)
  {
    MyNum = num;
  }
}

What is difference between Init-Only and ReadOnly in C# 9?

Also and before C# 9, without a get-only auto-property, to have a property coupled with a private field, and to remove the Visual Studio refactoring assitant suggestion, without disabling this module, you can simply use a classic getter method to avoid the Visual Studio code refactoring suggestion:

public class Foo
{
  private readonly int _myNum;
  public int GetMyNum() => _myNum;
  public Foo(int num)
  {
    _myNum = num;
  }
}