PiotrWolkowski
PiotrWolkowski

Reputation: 8792

Why does C# 8.0 allow readonly members in a struct but not in a class?

C# 8.0 introduced readonly members in a struct (as explained here). So for instance you can have this method:

public readonly override string ToString() => $"({X}, {Y}) is {Distance} from the origin";

Also, if your readonly method modifies a state of the struct it won't compile - which I find quite useful and an elegant solution. So for instance, in the example below if X and Y are properties of a struct the following method won't compile:

public readonly void Translate(int xOffset, int yOffset)
{
    X += xOffset;
    Y += yOffset;
}

Again, very useful and an elegant way to express the intention of the code.

Why then is it only possible with structs and not with classes? If I try to add readonly to a method in a class I get a compiler error:

The modifier 'readonly' is not valid for this item.

Are there any limitations of a reference type where having a readonly method doesn't make sense?

Upvotes: 8

Views: 2085

Answers (1)

Code Pope
Code Pope

Reputation: 5459

According to my opinion, there are two reasons why C# 8.0 only provides read-only members for structs:

  1. Structs are value types. When you call a method and pass the struct as a parameter, the compiler creates a deep copy of the struct instances. As the documentation shows:

    public static class MyClass
    {
        public static float ExistingBehavior(in Vector2 vector)
        {
            return vector.GetLength();
        }
    
        public static float ReadonlyBehavior(in Vector2 vector)
        {
            return vector.GetLengthReadonly();
        }
    }
    

    Here, vector is a struct. By default, when calling the method ExistingBehavior, the compiler creates a hidden copy of the vector class. Prior to C# 8.0, by making the whole struct vector read-only, a hidden copy would be prevented, which under specific circumstances could result in performance advantages. But what if not the whole struct is immutable?

    Now, with the new feature in C# 8.0, it is possible to only make a specific method read-only and to prevent creating a hidden copy by the compiler. For reference types like classes and interfaces, there is no performance advantage as the instance is passed by reference and a hidden copy is never made. Therefore, there is no benefit to add this feature to classes and interfaces.

  2. Another reason is that this is an extension to the concept of read-only structs, but there is not read-only interfaces or classes.

Upvotes: 8

Related Questions