7

Sometimes I would like to declare a property like this:

public string Name { get; readonly set; }

I am wondering if anyone sees a reason why such a syntax shouldn't exist. I believe that because it is a subset of "get; private set;", it could only make code more robust.

My feeling is that such setters would be extremely DI friendly, but of course I'm more interested in hearing your opinions than my own, so what do you think?

I am aware of 'public readonly' fields, but those are not interface friendly so I don't even consider them. That said, I don't mind if you bring them up into the discussion

Edit

I realize reading the comments that perhaps my idea is a little confusing. The ultimate purpose of this new syntax would be to have an automatic property syntax that specifies that the backing private field should be readonly. Basically declaring a property using my hypothetical syntax

public string Name { get; readonly set; }

would be interpreted by C# as:

private readonly string name;
public string Name
{
    get
    {
        return this.name;
    }
}

And the reason I say this would be DI friendly is because when we rely heavily on constructor injection, I believe it is good practice to declare our constructor injected fields as readonly.

9
  • 1
    Because properties is just syntactic sugar over get/set methods. And it would be nice if you expanded more on what you mean by "ID friendly"
    – Euphoric
    Commented Oct 12, 2012 at 12:48
  • 1
    I think he means Dependency Injection friendly. Commented Oct 12, 2012 at 13:09
  • I have no clue what you think it would do differently. Are you suggesting it would be settable by a DI container but not by anything else?
    – pdr
    Commented Oct 12, 2012 at 13:44
  • Wyatt is right. @pdr nothing would go different, but it would allow me to use automatic property syntax while keeping my constructor injected fields readonly. Right now, if i want to use the automatic property syntax, I can specify that the backing field should be private ("private set;") but not readonly. Commented Oct 12, 2012 at 14:21
  • @LuisFerrao: Your update helped me clarify my own issues with the question. I was taking issue with the wrong thing. I have answered it now.
    – pdr
    Commented Oct 12, 2012 at 14:32

3 Answers 3

9

The C# team has considered that this would be a very useful feature, and that's why in C# 6, they implemented it (just a little different from your proposal).

Getter-only auto-properties

This new kind of properties are getter-only, but can be set either inline or in the constructor. This means they are backed internally by a readonly field.

Instead of declaring a property as readonly set, you simply not declare it.

Inline assignment

public class Customer
{
    public string First { get; } = "Jane";
    public string Last { get; } = "Doe";
}

Constructor assignment

public class Customer
{
    public string Name { get; }
    public Customer(string first, string last)
    {
        Name = first + " " + last;
    }
}

You can read about this and other new features of C# 6 in the Roslyn wiki in GitHub.

3
  • 3
    This is a feature I greatly appreciate. Commented Sep 16, 2015 at 18:31
  • Do you know for a fact that the honest-to-goodness C# team considered my very proposal? Cause that would be pretty flattering :) Commented Sep 18, 2015 at 7:54
  • 1
    @LuisFerrao, hahaha, I have no way to know, but you were not the only one proposing it. Commented Sep 18, 2015 at 11:04
4

As mentioned in the comments, properties are just syntactic sugar. When they are turned into methods, "readonly" would no longer be syntactically correct.

You can expose a private variable through a read-only property for the desired effect:

private readonly string _name;

public string Name {
    get {
        return _name;
    }
}

public MyObject(string injectedName) {
    _name = injectedName;
}

Edit:

How do you envision your idea would work (if it was possible)? Your readonly property wouldn't work in an initialization list because the constructor is already finished executing at that point.

4
  • How is that significantly different from { get; private set; }?
    – pdr
    Commented Oct 12, 2012 at 13:42
  • 1
    @pdr With private set, you can set the property outside of the constructor / field initialization. With readonly field, you can't do that, which means it actually ensures immutability of that property. But I'm assuming you already knew that, so I guess I don't understand your question.
    – svick
    Commented Oct 12, 2012 at 13:58
  • 1
    @pdr The external interface of the class is the same, but while doing maintenance on the class a readonly field communicates that it may only be changed once (in the constructor), and a private setter means that you can change it from anywhere inside the class.
    – dvdvorle
    Commented Oct 12, 2012 at 14:00
  • Simon, I updated my question, let me know if it makes more sense. Commented Oct 12, 2012 at 14:14
3

I think your problem is that you're automatically assuming a getter for each injected property.

Auto-properties with private setters are for types where you have

public class Person
{
    public string Name { get; private set; }
    public int Age { get; private set; }

    public Person (string name, int age)
    {
        Name = name;
        Age = age;
    }
}

and very little logic. This means it doesn't matter if you can, technically speaking, set your auto-properties outside of the constructor. You probably won't. And, as far as an external class goes, you're still immutable.

But you don't use DI to generate objects like this one.

You use DI to inject services that you apply logic to, like this:

public Foo : IFoo
{
    private IBar _bar;
    private IGrommit _grommit;

    public Foo(IBar bar, IGrommit grommit)
    {
        _bar = bar;
        _grommit = grommit;
    }

    public string GrommitMyBarForAName()
    {
        return _grommit.DoStuff(bar).Name;
    }
}

In these cases, you should not automatically add an accessor for _bar, just because you can. You don't want to give public access to it, not even readonly.

There will be cases when you feel you have to but, in those cases, you should first reconsider your design. It's probably wrong.

If you're absolutely positive that you should, then add a standard accessor, but this should not be a common enough situation that you feel a need to complain that there should be a syntax to allow you to have an auto-property for it.

9
  • @LuisFerrao: They can. They often aren't. And, where they are, they should still be private. See the "tell, don't ask" principle: pragprog.com/articles/tell-dont-ask
    – pdr
    Commented Oct 12, 2012 at 15:33
  • After carefully reading your reply, I realizing where you are getting at. In my example, I use Name because I'm talking about C# syntax in general, but the property in my example can be of an abstract type. You seem to imply that public getters defeat the purpose of DI, which is confusing me. Using your exact example, imagine IFoo is itself a member of IParentFoo, from IGrandpa I might just want to foreach (var parentFoo in _parentFooList) parentFoo.IFoo.GrommitMyBarForAName(), in which case an IFoo public getter comes in handy... Commented Oct 12, 2012 at 15:42
  • ...without getters, IParentFoo would need itself a wrapper method that would call _iFoo.GrommitMyBarForAName() just so that IGrandpa can call _parentFoo.WrapperMethodForGrommitMyBarForAName(). This wrapper method would just be duplication of code and it might not even make sense for IParentFoo. Commented Oct 12, 2012 at 15:45
  • 1
    I'm +1ing you anyway for your GrommitMyBarForAName() method name :) (or I would if I had the reputation) Commented Oct 12, 2012 at 15:48
  • @LuisFerrao: If it doesn't make sense for IParentFoo then it shouldn't be part of it. Let IGrandpa have the reference to _foo.
    – pdr
    Commented Oct 12, 2012 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.