Read-Only Properties

How to implement a read only property

C# 6.0 adds readonly auto properties

public object MyProperty { get; }

So when you don't need to support older compilers you can have a truly readonly property with code that's just as concise as a readonly field.


Versioning:

I think it doesn't make much difference if you are only interested in source compatibility.

Using a property is better for binary compatibility since you can replace it by a property which has a setter without breaking compiled code depending on your library.

Convention:

You are following the convention. In cases like this where the differences between the two possibilities are relatively minor following the convention is better. One case where it might come back to bite you is reflection based code. It might only accept properties and not fields, for example a property editor/viewer.

Serialization

Changing from field to property will probably break a lot of serializers. And AFAIK XmlSerializer does only serialize public properties and not public fields.

Using an Autoproperty

Another common Variation is using an autoproperty with a private setter. While this is short and a property it doesn't enforce the readonlyness. So I prefer the other ones.

Readonly field is selfdocumenting

There is one advantage of the field though:

It makes it clear at a glance at the public interface that it's actually immutable (barring reflection). Whereas in case of a property you can only see that you cannot change it, so you'd have to refer to the documentation or implementation.

But to be honest I use the first one quite often in application code since I'm lazy. In libraries I'm typically more thorough and follow the convention.

When should use Readonly and Get only properties

Creating a property with only a getter makes your property read-only for any code that is outside the class.

You can however change the value using methods provided by your class :

public class FuelConsumption {
private double fuel;
public double Fuel
{
get { return this.fuel; }
}
public void FillFuelTank(double amount)
{
this.fuel += amount;
}
}

public static void Main()
{
FuelConsumption f = new FuelConsumption();

double a;
a = f.Fuel; // Will work
f.Fuel = a; // Does not compile

f.FillFuelTank(10); // Value is changed from the method's code
}

Setting the private field of your class as readonly allows you to set the field value only in the constructor of the class (using an inline assignment or a defined constructor method).
You will not be able to change it later.

public class ReadOnlyFields {
private readonly double a = 2.0;
private readonly double b;

public ReadOnlyFields()
{
this.b = 4.0;
}
}

readonly class fields are often used for variables that are initialized during class construction, and will never be changed later on.

In short, if you need to ensure your property value will never be changed from the outside, but you need to be able to change it from inside your class code, use a "Get-only" property.

If you need to store a value which will never change once its initial value has been set, use a readonly field.

What is the definition of a read-only property in JavaScript? What does it mean?

A read-only property means it cannot be overwritten or assigned to. Any such assignment will silently do nothing in non-strict mode. E.g.:





var obj = {};
Object.defineProperty(obj, 'property', {value: 123, writeable: false})


// Assign 456 to obj.property using the . syntax, but it's still 123
obj.property = 456;
console.log(obj.property);

// Assign 789 to obj.property using the [] syntax, but it's still 123
obj['property'] = 789;
console.log(obj['property']);

Read-Only Property in C# 6.0

Your example is using string constants which can't show all the possibilities. Look at this snippet:

class Foo
{
public DateTime Created { get; } = DateTime.Now; // construction timestamp

public int X { get; }

public Foo(int n)
{
X = n; // writeable in constructor only
}
}

Read only properties are per-instance and can be set from the constructor. Very different from a const field whose value must be determined at compile time. The property initializer is a separate feature and follows the rules and limitations of field initializers.

Set a read only property defined in a interface within a concrete class

This doesn't have anything to do with the interface, you're just declaring the property incorrectly. In C# 6, you can create a read-only property like this:

public class Person : IPerson
{
public Person()
{
Name = "Person";
}

public string Name { get; }
}

In earlier versions, you can use a read-only backing field which you can set:

public class Person : IPerson
{
private readonly string _name;

public Person()
{
_name = "Person";
}

public string Name
{
get { return _name; }
}
}

Note that the interface only requires the property has a getter, the implementation doesn't have to be read-only. You could add a setter if you had reason to modify the value:

public class Person : IPerson
{
public Person()
{
Name = "Person";
}

public string Name { get; set; }
}

The setter could be private if you only needed to be able to change the value from within the class.

Why can a read only property be assigned via constructor?

It can only be assigned in the constructor or in the initializer for the property declaration - just like a read-only field can only be assigned in the constructor or in the field initializer.

There won't be a property setter generated - the compiler will use a read-only field, and initialize it in the constructor. So the generated code will be broadly equivalent to:

class Person
{
private readonly string _name;

// Old school: public string Name { get { return _name; } }
public string Name => _name;

public Person(string name)
{
_name = name;
}
}

It's enormously useful to be able to do this, and I'm really glad it was added to C# 6.

Read-Only properties

Something like this? (as suggested by @vacawama in the comments)

struct Triangle {
let edgeA: Int
let edgeB: Int
let edgeC: Int

var isEquilateral: Bool {
return (edgeA, edgeB) == (edgeB, edgeC)
}
}

Let's test it

let triangle = Triangle(edgeA: 5, edgeB: 5, edgeC: 5)
triangle.isEquilateral // true

or

let triangle = Triangle(edgeA: 2, edgeB: 2, edgeC: 1)
triangle.isEquilateral // false

Defining read-only properties in JavaScript

You could instead use the writable property of the property descriptor, which prevents the need for a get accessor:

var obj = {};
Object.defineProperty(obj, "prop", {
value: "test",
writable: false
});

As mentioned in the comments, the writable option defaults to false so you can omit it in this case:

Object.defineProperty(obj, "prop", {
value: "test"
});

This is ECMAScript 5 so won't work in older browsers.

readonly properties and ngOnInit

You can't mark a method as a constructor there is just no syntax for that. You can break the readonly which is just a compile time check by using a type assertion to any and access any public/private property you want in a type unsafe way. You can also use a mapped type to make the type mutable, but it only works for public properties:

type Mutable<T> = { -readonly [ P in keyof T]: T[P] }

class Foo {
public readonly data: string;
private readonly pdata: string;
public init() {
const ref: Mutable<this> = this;
ref.data = ""
const pRef = this as any;
pRef.pdata = ""

const pSaferRef: { pdata: string } = this as any;
pSaferRef.pdata = ""
}
}


Related Topics



Leave a reply



Submit