10

Automatic properties let me replace this code:

private MyType myProperty;
public MyType MyProperty
{
    get { return myPropertyField; }
}

with this code:

public MyType MyProperty { get; private set; }

with a few changes here and there - but is there a way to replace this code:

private readonly MyType myProperty;
public MyType MyProperty
{
    get { return myPropertyField; }
}

with something similar?

Simon
  • 24,010
  • 36
  • 139
  • 249
  • I was looking for this myself some time ago (I was hoping something like `public readonly MyType MyProperty { get; private set; }` would work), but I ended up using the syntax in the bottom of your question. – Blixt Oct 08 '09 at 09:50
  • possible duplicate of [Is it possible to force an auto-property to use a readonly backing field?](http://stackoverflow.com/questions/1050761/is-it-possible-to-force-an-auto-property-to-use-a-readonly-backing-field) – nawfal May 05 '13 at 17:01

6 Answers6

10

Indeed, there is no way to do this at present.

We realize that in C# 3 we produced a bit of a philosophical oxymoron. The design of LINQ is heavily steeped in traditional immutable functional style of programming -- execution is deferred, queries are represented by immutable monads, expression trees are immutable, and so on.

And yet at the same time object initializers, collection initializers and auto props all encourage a traditional mutable-component-based style of programming. It seems like we are pushing in both directions -- which is indicative of the nature of C#; it's a pragmatic programming language that supports many different styles of programming.

However, since we are all big fans of the immutable style of programming, and since we believe that this style will pay dividends in making it easier to ensure the correctness of massively multithreaded applications in future ubiquitous multi-core architectures, we're definitely interested in figuring out some way to tame the mutability we've introduced. Readonly autoprops are one obvious way to do that; a small step, but a good one.

That all said, we have not even shipped C# 4 yet, and have not announced that there will be any new language features after that. You should treat all my musings about hypothetical features of unannounced products as "for entertainment purposes only" speculations, not as promises or announcements.

Eric Lippert
  • 612,321
  • 166
  • 1,175
  • 2,033
  • A related feature I'd like to see would be a means via which field initializers could make use of constructor parameters. By my understanding, field initializers are effectively just code inserted before the first statement of the constructor, and are run within that context, so they could have access to those parameters if the language provided a means to do so. My suggested implementation: a field-like syntax to specify that a certain named coonstructor parameter of a given type will be available to field initializers; all constructors of that type must then either have such a parameter... – supercat Dec 20 '12 at 15:40
  • ...or chain to one that does. This would allow something like a class that represents a collection of a constructor-specified (and unchangeable) size to have the declaration of an array initialize it with the proper size. If that's the only time that reference will ever get written, putting it in the declaration seems nicer than having to have it declared in one place and initialized in another. – supercat Dec 20 '12 at 15:43
  • @supercat: Interesting idea. And indeed, the C# design team is considering a slightly different mechanism. They are considering adding syntactic sugars to constructors to make it easier to express the idea "this ctor formal parameter initializes this readonly field", to make it easier to write immutable types concisely. I wouldn't expect the feature to ship any time soon though. – Eric Lippert Dec 20 '12 at 15:46
  • Glad you like the idea; I hope both the C# and vb.net teams can incorporate versions where the passed-in thing becomes a real field (with specifiable accessibility), an auto-property (likewise), or a variable which is only usable within the initializers or constructor. In vb.net, it's possible to achieve the desired semantics if the parameter values of interest should be held in fields, and if one adds an extra layer of inheritance (if a base class constructor stores the values in fields, the derived-class initializers can use them) but it's a little ugly. I don't think C# can do it at all. – supercat Dec 21 '12 at 16:06
7

No, but this idea is being tracked on Connect.

Mark Seemann
  • 209,566
  • 41
  • 390
  • 671
5

No, unfortunately not. I would very much like the feature, which could look like this:

public readonly string Name { get; }

or (slightly oddly)

public readonly string Name { get; readonly set; }

This would be converted into something like:

private readonly string <>_Name;

public string Name { get { return <>_Name; } }

The twist is that setter calls would be allowed - but only within the constructor. Such calls would be converted directly into assignments to the backing field.

I would dearly, dearly love such a feature. Maybe for C# 5...

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • I prefer your first example, but should not the `set` keyword be specified too, even if a property always has a setter? Especially since the setter can have different access levels even if it is `readonly` (right? I'm thinking of `private` and `protected`.) – Blixt Oct 08 '09 at 09:54
  • "...even if a property always..." -- to clarify, I mean auto-properties, not "normal" properties. – Blixt Oct 08 '09 at 09:56
  • @Blixt: Possibly. I guess the implication is "it's an auto-property, so there must be some way to set it..." I suspect that any combination is going to be awkward somewhere :) – Jon Skeet Oct 08 '09 at 10:13
  • I suppose. But what if you change the `private` in your third code block to `protected`? What should the short-hand code be to produce that output? – Blixt Oct 08 '09 at 10:18
  • @Blixt: You shouldn't be able to do that, IMO. Automatic properties *always* have private backing fields... and I wouldn't want readonly ones to be able to be set from derived constructors anyway. – Jon Skeet Oct 08 '09 at 10:41
  • True, but I would say that is because there is no reason whatsoever to have the backing field accessible. For `readonly` the situation is different, since the backing field *must* be accessed directly by your code (once compiled.) And since it *is* possible to have a `protected` field, you might be preventing some kind of case where `protected readonly` makes sense by only supporting `private`. I wouldn't use `protected` either, but I've seen cases where limiting functionality based on these kinds of assumptions have prevented some neat functionality (such as `where T : Enum`.) – Blixt Oct 08 '09 at 11:24
  • Well you could make the *getter* accessible to derived classes - and if you're already thinking that the derived class may want to be able to set the value of the field, what's to stop you from making a protected constructor which takes the value to set? I guess I don't feel too strongly on this either way, but the main thing is to get this feature into the language in the first place :) – Jon Skeet Oct 08 '09 at 11:34
  • I see your point and I'm not really that sensitive about it either =) But my point is just that one should avoid disallowing functionality that is practically there unless you have a very good reason to do so. – Blixt Oct 08 '09 at 11:37
  • 2
    I've seen people asking elsewhere for support for methods that can only be called from the constructor, but which can modify readonly variables. Perhaps the setter could be that sort of feature. I'm not sure what you'd call them in C# - the managed C++ 'initonly' keyword is actually more descriptive than C#'s 'readonly' keyword. – Simon Oct 09 '09 at 09:00
  • @Simon: I haven't heard of that feature request before, but it makes a lot of sense. – Jon Skeet Oct 09 '09 at 09:30
1

readonly can only be applied to fields, so I believe not.

Could you not just use:

public readonly MyType MyProperty;

as it is then only assignable from the constructor anyway?

JDunkerley
  • 11,869
  • 5
  • 39
  • 45
  • The "good design" gurus will kill you for this, but I give you +1 because it actually works and never seems to cause any problems in practice, and also for compensation for future downvotes. – erikkallen Oct 08 '09 at 09:40
  • 2
    See my response to Jan Bannister... there are plenty of reasons not to use public fields, even readonly ones. – Jon Skeet Oct 08 '09 at 09:50
1

No, there's no way you can do it. In fact, I don't see why would you want to get a value of a property which has not been set previously. For obvious reasons, you cannot set the value if there's neither set accessor, nor backing field.

Anton Gogolev
  • 107,051
  • 37
  • 191
  • 278
-1

That's really convoluted mate.

Just make it a public readonly field.

Jan Bannister
  • 4,592
  • 8
  • 35
  • 44
  • 1
    At which point you lose all the benefits of properties - including source and binary compatibility when you eventually want to write a more fully-fledged property implementation. Public instance fields are a bad idea IMO. – Jon Skeet Oct 08 '09 at 09:47
  • I would normally agree that you should never use public fields. But this a weird use case. It's read only, it's not meant to be written to. – Jan Bannister Oct 08 '09 at 10:29
  • @Jan: Imagine if you compile your `readonly` field, then later it is replaced by a property with only a public get accessor (which could still return the value of a `private readonly` field.) This will break binary compatability. – Blixt Oct 08 '09 at 11:34
  • @Jan: Just because it's read only doesn't mean you might not want to put extra logic in there eventually. Likewise, the philosophical objection to exposing fields (they're an implementation detail, unlike properties which are part of the API) doesn't go away just because it's read only. Glad you liked the book though :) – Jon Skeet Oct 08 '09 at 11:36
  • You missed another advantage of properties over fields: properties can be members of interfaces but fields cannot. – finnw Nov 03 '09 at 15:52
  • @Blixt, @Tony the Pony OK OK OK. These are all lovely comments but they all address possible future changes and not the actual question. So you are over engineering your answers. Which is common, don't worry about it. – Jan Bannister Nov 04 '09 at 11:00