5

Sometimes I see classes defined with readonly members like so:

class Foo
{
    private readonly string bar;

    public Foo(string bar)
    {
        this.bar = bar;
    }

    public string Bar => bar;
}

and other times I see classes defined with readonly members like so:

class Foo
{
    public Foo(string bar)
    {
        Bar = bar;
    }

    public string Bar { get; private set; }
}

The second example looks a lot more readable/succinct to me, but I was wondering if there is any legitimate reason for explicitly defining a readonly backing field (as per the first example) ?

Qudos for an in-depth analysis of the two examples, ideally covering what's really going on under the hood, in the CLR.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
Matthew Layton
  • 39,871
  • 52
  • 185
  • 313

1 Answers1

9

The first is a short way of writing

class Foo
{
    private readonly string bar;
    public Foo(string bar)
    {
        this.bar = bar;
    }
    public string get_Bar() { return this.bar; }
}

That's all a property with a getter is; it's just a short way of writing a getter function.

The second is a short way of writing

class Foo
{
  private string __bar;
  public Foo(string bar)
  {
      this.set_Bar(bar);
  }
  public string get_Bar() { return this.__bar; }
  private void set_Bar(string b) { this.__bar = b; }
}

Where again, a property is just a pair of get/set methods behind the scenes.

I was wondering if there is any legitimate reason for explicitly defining a readonly backing field

Either form is perfectly legitimate. Pick the one you like better.

I note that the two forms are not equivalent. In the first case the property's backing field can only be changed in the constructor; in the latter, the property's backing field can be changed anywhere in the class.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Does reflection have any impact on either? – Matthew Layton Dec 19 '16 at 19:17
  • @series0ne: I don't understand the question. – Eric Lippert Dec 19 '16 at 19:17
  • Well presumably I can't call a setter on the first example since it doesn't have one, and presumably regardless of it being readonly, reflection would let me change the value willy-nilly? – Matthew Layton Dec 19 '16 at 19:21
  • 1
    @series0ne: If your component is granted private reflection permission then your component can do literally anything it wants. Full trust means **full trust** -- you get to break the rules and are responsible for understanding the **full** consequences of doing so. If you feel like using private reflection permission to muck around with values of implementation details, that's your right. – Eric Lippert Dec 19 '16 at 19:23
  • Isn't the last paragraph in the answer the only thing that matters in deciding what to use? If you want to alter the value outside the constructor don't use a readonly backing field otherwise leave it readonly or am I missing something? – Nope Dec 20 '16 at 09:16
  • For the sake of completeness, could you also explain the new feature (readonly) auto implemented property without `set` and its equivalent with backing field? – Second Person Shooter Feb 02 '18 at 02:37