6

C# 6 added auto-property initializers and so we can do

private List<LinearLayout> layouts1 { get; } = new List<LinearLayout>();

Is this better or worse than

private readonly List<LinearLayout> layouts2 = new List<LinearLayout>();

(N.B. this is related to the 2011 question .NET Properties - Use Private Set or ReadOnly Property?, but that includes a public getter alongside a private setter. Here I only have a private getter.)

  • Better or worse by what measure? Also, I don't believe they are entirely interchangable (in your case they are). There are situations where you could set a readonly property to something you would never be able to with an auto property with only a get. – Becuzz Jun 12 '18 at 14:17
  • 1
    What ever is the point of a private getter or setter (auto-generated or not) of a private field given no field transformation? – radarbob Jun 12 '18 at 15:26
  • @radarbob, perhaps to represent a contract to myself, in this case to not set the field – dumbledad Jun 13 '18 at 7:41
9

If you take a look here, you'll see that the following code:

class Example
{
   private List<LinearLayout> layouts1 { get; } = new List<LinearLayout>();
}

Is lowered by the compiler to:

internal class Example
{
    private readonly List<LinearLayout> <layouts1>k__BackingField = new List<LinearLayout>();

    private List<LinearLayout> layouts1
    {
        get
        {
            return <layouts1>k__BackingField;
        }
    }
}

and the property gets further lowered to a get_layouts1() method.

In other words, auto-property initializers are pure syntactic sugar. They provide a means of using auto-properties, whilst still allowing the backing field to be initialised.

So from a mutability point of view, there's no difference between them at all. Both provide read-only access to a list that is initialised when an instance of the class is created.

It's possible that it creates a slight performance overhead as the method must be called to obtain the list reference, but it's likely that the CLR JIT optimises the method away and just accesses the field directly.

The most obvious use for private properties is for lazy loading/deferred execution purposes. There are other uses, but as a guideline, they are often pointless "noise". I'd not go so far as to say that using a private property is worse than just using a field, but I'd advise just using a read-only field for most cases.

  • 3
    Thanks - I'm not sure the only real use is lazy loading or deferred execution, some of the other answers to that question are interesting, for example EricLippert uses them for debugging (here), JaredPar and others for calculated values (here), MattGreer as contracts with himself (here), and YohanesNurcahyo to improve readability (here) – dumbledad Jun 13 '18 at 8:11
  • @dumbledad, good point. I have tried to rephrase that last part to reflect that as I'm not going to argue with the likes of Eric Lippert! :) – David Arno Jun 13 '18 at 8:23
0

In this case they would function almost identically. There is one subtlety that would make the private property less than ideal:

  • The bytecode would access the List<LinearLayout> through a getter function. However, as soon as the bytecode is recompiled for your environment (which C# has done for a long time), the getter function would be optimized out, so not a real problem.

If they are used identically, there won't be any practical difference.

  • To be crystal-clear, readonly doesn't make the list immutable; it merely prevents someone from assigning a different list to the member variable. – Robert Harvey Jun 12 '18 at 15:06
  • 1
    @BerinLoritsch, "You can set a private property". This is incorrect. There is no "implicit private setter". The setter has to be explicitly specified with set. private List<LinearLayout> layouts1 { get; } is read-only. – David Arno Jun 12 '18 at 18:17
  • Going by codebetter.com/derikwhittaker/2014/11/18/…, @DavidArno seems to be correct. When you declare a property with { get; }, there is no private setter at all. However, C# 6 made it so you can change the value of a get-only auto-implemented property within a constructor, by assigning to the backing field. You code this as though you were assigning to the property. In any case, the backing field is readonly, so the statement that "unlike the readonly private field, the private property is mutable" is incorrect. – Tanner Swett Jun 12 '18 at 20:12
  • 1
    @BerinLoritsch I just did a test and @DavidArno & @TannerSwett are correct. If I later try to set layouts1 I get the error "Property or indexer 'MainActivity.layouts1' cannot be assigned to -- it is read only" and if I try to set layouts2 I get the error "A readonly field cannot be assigned to (except in a constructor or a variable initializer)" so there is no implicit private setter, at least none one can use. – dumbledad Jun 13 '18 at 6:48
  • I have removed the misremembered information. – Berin Loritsch Jun 13 '18 at 14:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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