Automated Property with Getter Only, Can Be Set, Why

Automated property with getter only, can be set, why?

This is a new C# 6 feature, "Getter-only auto-properties", also known as "Auto-Property Initializers for Read-Only Properties" as discussed in this MSDN magazine article 'C# : The New and Improved C# 6.0' by Mark Michaelis and in the C# 6.0 draft Language Specification.

The read-only field's setter is only accessible in the constructor, in all other scenarios the field is still read only and behaves as before.

This is a convenience syntax to reduce the amount of code you need to type and to remove the need to explicitly declare a private module level variable to hold the value.

This feature was seen as important as, since the introduction of Auto-Implemented Properties in C#3, mutable properties (those with a getter and setter) had become quicker to write than immutable ones (those with only a getter), meaning people were being tempted to use mutable properties to avoid having to type the code for a backing field usually required for read-only properties. There is more discussion of Auto-Implemented properties in the relevant section of the Microsoft C# Programming Guide.

This blog post, '#1,207 – C# 6.0 – Auto-Property Initializers for Read-Only Properties' by Sean Sexton Has a good explanation and example as follows:

Prior to C# 6.0, if you wanted a read-only (immutable) property, you’d
typically use a read-only backing field that is initialized in the
constructor, as shown below.

public class Dog 
{
public string Name { get; set; }

// DogCreationTime is immutable
private readonly DateTime creTime;
public DateTime DogCreationTime
{
get { return creTime; }
}

public Dog(string name)
{
Name = name;
creTime = DateTime.Now;
}
}

In C# 6.0, you can use auto-implemented properties to implement a
read-only property. You do this by using an auto-property
initializer. The result is much cleaner than the above example, where
we had to explicitly declare a backing field.

public class Dog
{
public string Name { get; set; }

// DogCreationTime is immutable
public DateTime DogCreationTime { get; } = DateTime.Now;

public Dog(string name)
{
Name = name;
}
}

More details can also be found in the dotnet Roslyn repo on GitHub:

Auto-properties can now be declared without a setter.

The backing field of a getter-only auto-property is implicitly
declared as readonly (though this matters only for reflection
purposes). It can be initialized through an initializer on the
property as in the example above. Also, a getter-only property can be
assigned to in the declaring type’s constructor body, which causes the
value to be assigned directly to the underlying field:

This is about expressing types more concisely, but note that it also
removes an important difference in the language between mutable and
immutable types: auto-properties were a shorthand available only if
you were willing to make your class mutable, and so the temptation to
default to that was great. Now, with getter-only auto-properties, the
playing field has been leveled between mutable and immutable.

and in the C# 6.0 draft Language Specification (NB: The language specification is final as far as Microsoft are concerned, but it is yet to be approved as a EMCA/ISO standard, hence the 'draft'):

Automatically implemented properties

An automatically implemented property (or auto-property for short), is
a non-abstract non-extern property with semicolon-only accessor
bodies. Auto-properties must have a get accessor and can optionally
have a set accessor.

When a property is specified as an automatically implemented property,
a hidden backing field is automatically available for the property,
and the accessors are implemented to read from and write to that
backing field. If the auto-property has no set accessor, the backing
field is considered readonly (Readonly fields). Just like a readonly
field, a getter-only auto-property can also be assigned to in the body
of a constructor of the enclosing class. Such an assignment assigns
directly to the readonly backing field of the property.

An auto-property may optionally have a property_initializer, which is
applied directly to the backing field as a variable_initializer
(Variable initializers).

Property with getter only vs. with getter and private setter

public string MyProp { get; } - This is introduced in C# 6.0. And such properties are called read-only auto-properties. Assignments to such members can only occur as part of the declaration or in a constructor in the same class. You can read detailed explanation about it in that MSDN article or in Jon Skeet blog. As explained in that article, such property solves four problem automatically:

  • A read-only-defined backing field
  • Initialization of the backing field from within the constructor
  • Explicit implementation of the property (rather than using an auto-property)
  • An explicit getter implementation that returns the backing field

public string MyProp { get; private set; } - This means that the property is read-only in the outside of this class, but you can change it's value inside of this class.

By the way, you can set read-only auto-properties value using new auto-initialize syntax which is again introduced in C# 6.0:

public string MyProp { get; } = "You cannot change me";

It is equal to this code for the previous versions of C#:

private readonly string myProp = "You cannot change me"
public string MyProp { get { return myProp ; } }

Or, this in C# 6.0:

public string MyProp { get; }
protected MyClass(string myProp, ...)
{
this.MyProp = myProp;
...
}

is equal to this in the previous versions:

private readonly string myProp;
public string MyProp { get { return myProp; } }
protected MyClass(string myProp, ...)
{
this.myProp = myProp;
...
}

Does auto implemented properties have an implied set?

This is a newly introduced feature in C# 6.0. See the C# 6.0 Language specification, section 10.7.3 Automatically implemented properties:

If the auto-property has no set accessor, the backing field is
considered readonly (§10.5.2). Just like a readonly field, a
getter-only auto-property can also be assigned to in the body of a
constructor
of the enclosing class. Such an assignment assigns
directly to the readonly backing field of the property.

(Emphasis mine)

automated property with get or set only in visual studio 2015

It's because there is no sense of set-only auto-implemented property.

Your code could contains set-only property because it can cause a class state. But you can't do it with auto-implemented setter.

Instead of it you can initialize your read-only property with initializers for auto-properties or getter-only auto-properties and then get the value:

public int Foo { get; } = 3;

You can add whole expression to your initializer:

public string Config { get; } = string.IsNullOrWhiteSpace(string connectionString =
(string)Properties.Settings.Default.Context?["connectionString"])
? connectionString
: "<none>";

Also you can use Ctor assignment to getter-only autoprops.

Why does collection initializer work with getter-only property?

These other answers are almost right. Let's go through it and actually get it all right.

Why does a collection initializer work with a getter-only property?

Because the property value is not changed. The contents of the collection that the property refers to is what is changed.

Think of a property as a bucket. You can't change which bucket the property refers to, but you can change the contents of the bucket.

How do we get our names, if they are going to get in Students and respectively in _students, that were not assigned because of nonexistence of Students setter.

The Students property is never assigned, at all. How could it be? It has no setter.

The names are added to the collection referred to by the Students getter.

When I Initialize Students, I initialize _students ?

No. The initialization of _students is the line which assigns a value to _students.

The collection initializer adds values to an existing collection. The variable _students has already been initialized.

when I take variable from IEnumerable(some), I am take variable from Students ?

You don't take a variable from anything. You take values. Variables are not values; variables contain values. Don't confuse the storage with the value stored.

I can't understand, WHERE exactly I assign variables(INITALIZE) _students collections ?

The _students variable is initialized in the line that initializes _students. The contents of the collection are initialized in the line that has the contents.

Perhaps it will help to list everything that happens in exactly the order it happens:

  • a new Classroom object is created; the _students field is null; a reference to the object is produced.
  • a new empty list is created; a reference to the list is copied into the _students field of the newly-created Classroom object.
  • the Students getter is called on the reference to the new Classroom object. It returns the contents of _students, which is a reference to an empty list.
  • four items are added to that list
  • the reference to the Classroom object is copied to the classroom variable.

Or, in code, this is equivalent to:

c = create a Classroom
c._students = null
l1 = create a List<string>
c._students = l1
l2 = c.Students -- which returns c._students
l2.Add("...") -- four times
classRoom = c

See, there is never a setter of Students called. There doesn't need to be. All it does is gets the reference contained in _students, which already has been initialized by the field initializer.

How does a property without setter allow value to be assigned?

A read-only property can only be set:

  • If it's an auto-implemented property (i.e. the property body just has { get; })
  • When the setting the property is within the constructor

The read-only property is implemented as a read-only field, and when the property is set within the constructor, the read-only field is set directly.

So the code you've posted is equivalent to:

public class Startup
{
private readonly IConfiguration _configuration;
public IConfiguration Configuration => _configuration;

public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
}

Read-Only Auto-Property for Simple Types: Initializer VS Expression Body Getter

I suspect that the former uses a backing field

The auto-property initializer does in fact creating a backing field! You can throw this in ILSpy and see it in the output:

public class One
{
public bool AllowsDuplicates
{
[CompilerGenerated]
get
{
return this.<AllowsDuplicates>k__BackingField;
}
}

public One()
{
this.<AllowsDuplicates>k__BackingField = true;
base..ctor();
}
}

public class Two
{
public bool AllowsDuplicates
{
get
{
return true;
}
}
}

But is one of them preferred over the other?

For the specific example in the question, the auto-property would allow a constructor to ask for a bool and assign it. The second style would not. If the intent is to use it as a "default value" which can be modified once during construction, then an auto-property is the right choice.

class Test
{
// Could assign this in the second constructor
public bool AllowsDuplicates { get; } = true;

// Cannot assign this in the second constructor
public bool AllowsDuplicates => true;

public Test()
{
// Default value used
}

public Test(bool value)
{
AllowsDuplicates = value;
}
}

I've seen expression bodied syntax win out most when it's a cover for a small function that is utilized as a property. A struct in Eric Lippert's dedoublifier has a nice example of this:

public DoubleHelper(double d)
{
this.RawBits = (ulong)BitConverter.DoubleToInt64Bits(d);
}

public ulong RawBits { get; }
// RawSign is 1 if zero or negative, 0 if zero or positive
public int RawSign => (int)(RawBits >> 63);
public int RawExponent => (int)(RawBits >> 52) & 0x7FF;
public long RawMantissa => (long)(RawBits & 0x000FFFFFFFFFFFFF);
public bool IsNaN => RawExponent == 0x7ff && RawMantissa != 0;
public bool IsInfinity => RawExponent == 0x7ff && RawMantissa == 0;
public bool IsZero => RawExponent == 0 && RawMantissa == 0;
public bool IsDenormal => RawExponent == 0 && RawMantissa != 0;

There's one value which is assigned in the constructor, and the rest are property values which are computed based off of it.

Why can a full property in C# be overridden with only a getter but it can still be set?

I'll take a crack at this.

It looks like this may just be a bug with Intellisense, where it is unable to find the base implementation of an auto-property. The code is valid and makes sense - here's another way to express your example.

Child child = new Child();
child.SetProperty(true);

class Parent
{
private bool _property;

public virtual bool GetProperty() => _property;
public virtual void SetProperty(bool value) => _property = value;
}

class Child : Parent
{
public override bool GetProperty() => base.GetProperty();
}

With this representation, it's now obvious why overriding GetProperty is fine. Here's the relevant IL for your code:

Main:
IL_0000: newobj Child..ctor
IL_0005: ldc.i4.1
IL_0006: callvirt Parent.set_Property
IL_000B: ret

Parent.get_Property:
IL_0000: ldarg.0
IL_0001: ldfld Parent.<Property>k__BackingField
IL_0006: ret

Parent.set_Property:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld Parent.<Property>k__BackingField
IL_0007: ret

Parent..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret

Child.get_Property:
IL_0000: ldarg.0
IL_0001: call Parent.get_Property
IL_0006: ret

Child..ctor:
IL_0000: ldarg.0
IL_0001: call Parent..ctor
IL_0006: ret

And here's my version:

Main:
IL_0000: newobj Child..ctor
IL_0005: ldc.i4.1
IL_0006: callvirt Parent.SetProperty
IL_000B: ret

Parent.GetProperty:
IL_0000: ldarg.0
IL_0001: ldfld Parent._property
IL_0006: ret

Parent.SetProperty:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld Parent._property
IL_0007: ret

Parent..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret

Child.GetProperty:
IL_0000: ldarg.0
IL_0001: call Parent.GetProperty
IL_0006: ret

Child..ctor:
IL_0000: ldarg.0
IL_0001: call Parent..ctor
IL_0006: ret

Note that this is different than public override bool Property { get; }, being shorthand for instructing the compiler to generate a single getter override for a backing property of the same name, with no mention of the preexisting setter. Somebody experienced with the actual spec will definitely be able to offer more information around this, however.

automated property with get or set only in visual studio 2015

It's because there is no sense of set-only auto-implemented property.

Your code could contains set-only property because it can cause a class state. But you can't do it with auto-implemented setter.

Instead of it you can initialize your read-only property with initializers for auto-properties or getter-only auto-properties and then get the value:

public int Foo { get; } = 3;

You can add whole expression to your initializer:

public string Config { get; } = string.IsNullOrWhiteSpace(string connectionString =
(string)Properties.Settings.Default.Context?["connectionString"])
? connectionString
: "<none>";

Also you can use Ctor assignment to getter-only autoprops.

Explicit implementation of an interface using a getter-only auto-property (C# 6 feature)

You can get around this by using a read-only backing field for your explicitly implemented property. You can assign the injected value to the backing field within the constructor, the explicit property's get implementation will return it.

public class Impl : IFoo
{
private readonly string _testFoo;

string IFoo.TestFoo => _testFoo;

public Impl(string value)
{
_testFoo = value;
}
}


Related Topics



Leave a reply



Submit