13

My project contains a large number of classes with properties whose backing field is marked readonly as they are only set at construction. As a matter of style, I like using auto-properties as it eliminates a lot of boilerplate code and encourages use of the property member rather than the backing field. However, when using an auto-property I lose the "readonly-ness" of my backing field. I understand the compiler/runtime is able to take advantage of some performance enhancements when a field is marked this way, so I would like to be able to mark my auto-property as readonly, something like this:

[ReadOnly]
public string LastName { get; }

rather than

private readonly string _LastName;
public string LastName 
{ 
    get
    { 
        return _LastName;
    }
}

Is there some mechanism already available to do this? If not, is the performance gain from the custom backing field being readonly really worthwhile?

Exposing the field as public is another option, I suppose, it just seems wrong to expose a field that way. i.e.

public readonly string LastName;
JadeMason
  • 1,076
  • 1
  • 12
  • 22
  • 1
    I agree it seems wrong to expose a public readonly field. If it ever needed to change to a property later, the change would break compatibility. – Chris W. Rea Jun 26 '09 at 19:20
  • 2
    As the answers have correctly noted, no, there's no way to do this right now. This is a frequently requested feature and is definitely high on the list of possible new features for hypothetical future versions of the language. I personally would like to have a whole set of related features which encourage programming in an immutable style; this would be just one of them. – Eric Lippert Jun 26 '09 at 22:00

6 Answers6

14

I'm afraid not, but you can do this:

public string LastName { get; private set; }

Not quite as good as readonly, but not too bad.

mqp
  • 64,209
  • 13
  • 90
  • 122
9

No, unfortunately there's no way of doing this. Personally there are two things that I think are missing from automatically implemented properties in C# - a default value (which I believe will be in VB10) and readonly properties which can only be set in the constructor. In other words, I'd like to be able to do:

public class Foo
{
    public string Tag { get; internal set; } = "Default value";

    // The "readonly" would imply "private" as it could only
    // be set from a constructor in the same class
    public int Value { get; readonly set; }

    public Foo()
    {
        // Valid to set property here, but nowhere else
        Value = 20;
    }
}

As Jared mentioned, this would mean changing compiler calls to the property setter into simple field assignments, and making sure they only occurred in the constructor.

This would make writing immutable types simpler. Unfortunately the situation won't improve in C# 4. Let's hope we get something like this for C# 5...

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • In the meantime, is one preferred over the other? It appears that both the setter-less auto-property and the readonly backing field implementation provide an immutable implementation. Is it just a matter of style after that? – JadeMason Jun 26 '09 at 19:28
  • 5
    I personally stick to a readonly backing field unless it's throw-away code. I like know it's *properly* immutable, even if I accidentally try to set it within my own type. – Jon Skeet Jun 26 '09 at 19:29
  • Eugh! How can a setter be readonly? Perhaps public readonly int Value { get; set; } – Alun Harford Jun 26 '09 at 21:22
4

No it is not and if it was the feature would be useless without significant tweaking.

A readonly field can only be verifiably set from a constructor. A auto-implemented property can only be set from the generated setter. These are incompatible requirements and will produce unverifiable code.

Yes you could potentially make the compiler smart enough to ignore the setter and go straight to the backing field in the constructor. But in the setter itself would still be unverifiable. The compiler would need to omit it from the generated code as will producing a truly read-only property. This produces another contradiction because you would still need to do an assignment statement against the property.

Foo() {
  SomeProperty = "somevalue";
}

In this case the code looks like it's calling a setter on a property. But there is actually no setter to be called since it must be omitted from the final code.

EDIT

This is not saying it can't be done. It can but it would require a bit of work from C#.

In particular they would have to provide a way to set the backing field of a property which cannot have a setter. There are several ways this could be done.

  • Give users access to the backing field of an auto-implemented property
  • Allow the setter style syntax even though there is no setter and let the compiler translate it to a field access under the hood
  • Invent some new syntax

I'm not saying any of these are good options, just possibilities to make this type of feature work .

JaredPar
  • 673,544
  • 139
  • 1,186
  • 1,421
3

As of C# 6.0 the answer is yes. Your example can be written as below, and the compiler automatically generates a read-only field behind the property. This is called a getter-only auto-property.

public string LastName { get; }

From https://msdn.microsoft.com/en-us/magazine/dn879355.aspx

Getter-only auto-properties are available in both structs and class declarations, but they’re especially important to structs because of the best practice guideline that structs be immutable. Rather than the six or so lines needed to declare a read-only property and initialize it prior to C# 6.0, now a single-line declaration and the assignment from within the constructor are all that’s needed. Thus, declaration of immutable structs is now not only the correct programming pattern for structs, but also the simpler pattern—a much appreciated change from prior syntax where coding correctly required more effort.

kristianp
  • 4,574
  • 27
  • 52
1

I prefer the real readonly backing field, since this guarantees that I'm not changing that backing field after construction.

Lucero
  • 56,592
  • 6
  • 112
  • 151
1

No and no. There's no way to do this and there's no performance gain to readonly backing fields.

Jamie Ide
  • 45,803
  • 16
  • 74
  • 115
  • I've understood that 'static readonly' does allow the JIT to make some optimizations, like never making copies of the value. – JulianR Jun 26 '09 at 23:39
  • @JulianR -- There are no performance benefits as far as I know. See http://stackoverflow.com/questions/277010/what-are-the-benefits-to-marking-a-field-as-readonly-in-c – Jamie Ide Jun 27 '09 at 12:55