6

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 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 elegant way to express the intention of the code.

Why then it is 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?

PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68
  • Does this answer your question? [How can I make a read only version of a class?](https://stackoverflow.com/questions/2724731/how-can-i-make-a-read-only-version-of-a-class) – Pavel Anikhouski May 01 '20 at 12:12
  • The linked question is more related to immutability. In the case of read only members (particularly methods) I know you cannot do that on the class and only on a struct. But I do not understand the reason for that limitation. So in short the linked question, although useful, is not related to my question. – PiotrWolkowski May 01 '20 at 12:14
  • While classes cannot have `readonly` methods, I believe the [`Pure`](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.contracts.pureattribute?view=netcore-3.1) attribute applied to the method reflects the fact that it won't modify the state of the class. Keep in mind though, that this is not a guarantee – Emanuel Vintilă May 01 '20 at 12:56
  • @EmanuelVintilă So when the `readonly` is applied to a method of a struct if the method will try to modify the state of the struct (as in the example) it won't compile. I would consider that a reasonable guarantee. But that's only valid for structs. You cannot apply `readonly` on a method of a class. – PiotrWolkowski May 01 '20 at 13:00

1 Answers1

4

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 cicumstances could result in performance adventages. 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. Therfore, 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.

Code Pope
  • 5,075
  • 8
  • 26
  • 68