C# Get Only Property: Syntax and Usage
c# get only property: Learn how to define get-only properties in C#, assign values in constructors, use auto-property initializers, and understand the differences from...
c# get only property requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
A get-only property in C# exposes a value without allowing callers to change it from outside the class. This is a common requirement when you want to enforce immutability or control when a value can be set. The syntax is straightforward: you declare a property with only a get accessor, and you provide the value either through a constructor, an auto-property initializer, or a computed expression.
Declaring a Get-Only Property
The simplest form is an auto-property with only a getter:
public class Person { public string Name { get; } }
The compiler generates a private backing field and exposes it through the getter. Because there is no setter, the value of Name can only be assigned from within the class itself. This is a compile-time guarantee; any attempt to assign to Name from outside the class results in an error.
Assigning Values in the Constructor
The most common way to initialize a get-only auto-property is in the constructor:
public class Person { public string Name { get; } public Person(string name) { Name = name; } }
This assignment is allowed because the compiler treats the constructor as an internal initialization point. Once the constructor finishes, the property becomes effectively read-only. If you try to assign to Name in a method or from external code, the compiler rejects it. This pattern is ideal for immutable objects where the value is fixed at creation time.
Auto-Property Initializers for Get-Only Properties
You can also assign a default value directly at the declaration:
public class Person { public string Name { get; } = "Unknown"; }
The initializer runs before the constructor body, so the property always has a value even if the constructor does not assign it. This is useful for providing sensible defaults while still preventing later modification. Note that the initializer is evaluated for each instance, not at class load time.
Expression-Bodied Get-Only Properties
For computed values, you can use an expression-bodied getter:
public class Circle { public double Radius { get; } public double Area => Math.PI * Radius * Radius; }
Here Area is a get-only property that returns a calculated value each time it is accessed. This is syntactic sugar for a getter that returns the result of an expression. The value is not cached; if the calculation is expensive, you may need to cache it manually. Expression-bodied properties are concise and clearly express that the value is derived from other state.
Get-Only vs Init-Only vs Readonly Fields
C# provides several ways to create immutable members. The choice depends on whether you need property semantics and when assignment is allowed.
| Feature | Get-only property | Init-only property | Readonly field |
|---|---|---|---|
| Assignment outside constructor | Not allowed | Allowed during object initialization | Not allowed |
| Syntax | public string Name { get; } | public string Name { get; init; } | public readonly string Name; |
| Use case | Immutable after construction | Immutable after initialization, supports object initializers | Simple immutable value without property semantics |
The init-only accessor, introduced in C# 9, allows assignment in object initializers as well as constructors. This is useful when you want to build objects with a fluent initializer pattern but still keep them immutable afterward. A readonly field is a lower-level construct; it does not provide property encapsulation, so it cannot be overridden in derived classes or participate in interfaces.
When to Choose a Get-Only Property
Get-only properties are the right choice when you need to expose a value as part of a class's public contract but want to control when it is set. They work well with interfaces, data binding, and polymorphism. Unlike readonly fields, get-only properties can be virtual, and their implementation can be changed to include validation or logging later without affecting callers. If you use a readonly field and later need to add logic, you must change the public API to a property, which is a breaking change. Get-only properties give you that flexibility from the start.
For DTOs or simple data holders, a readonly field might be sufficient, but for most domain objects, a get-only property is a safer and more maintainable choice.
Common Pitfalls and Limitations
One limitation is that a get-only auto-property cannot be assigned from a method called by the constructor, even if that method is private. The compiler only allows direct assignment in the constructor body or via an initializer. If you need to initialize from a helper method, you must assign the result to a readonly field and expose it through a property, or use a constructor that takes the computed value.
Another pitfall is using a get-only property with a ref or out parameter. Because there is no setter, such usage is not allowed. The compiler will reject code like TryGetValue(property, out obj.Property).
Expression-bodied get-only properties recompute the value on every access. If the computation is expensive, consider storing the result in a readonly field during construction or using a caching mechanism. For most simple expressions, the overhead is negligible, but it is worth being aware of the behavior.
Finally, remember that get-only does not mean the returned object is immutable. If the property returns a reference type, the caller can still modify the object's internal state. The property only prevents reassignment of the reference itself.