== Why is this an issue? While the properties of a https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/readonly[`readonly`] https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types[reference type] field can still be changed after initialization, those of a `readonly` https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-types[value type] field, such as a https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct[`struct`], cannot. If the member could be either a `class` or a `struct` then assignment to its properties could be unreliable, working sometimes but not others. == How to fix it There are two ways to fix this issue: * Restrict the type of the field to a `class` * Remove the assignment entirely, if it is not possible to restrict the type of the field === Code examples ==== Noncompliant code example [source,csharp,diff-id=1,diff-type=noncompliant] ---- interface IPoint { int X { get; set; } int Y { get; set; } } class PointManager where T1 : IPoint where T2 : IPoint { readonly T1 point1; // this could be a struct readonly T2 point2; // this could be a struct public PointManager(T1 point1, T2 point2) { this.point1 = point1; this.point2 = point2; } public void MovePoints(int newX) { point1.X = newX; //Noncompliant: if point is a struct, then nothing happened point2.X = newX; //Noncompliant: if point is a struct, then nothing happened } } ---- ==== Compliant solution [source,csharp,diff-id=1,diff-type=compliant] ---- interface IPoint { int X { get; set; } int Y { get; set; } } class PointManager where T1 : IPoint where T2 : class, IPoint { readonly T1 point1; // this could be a struct readonly T2 point2; // this is a class public PointManager(T1 point1, T2 point2) { this.point1 = point1; this.point2 = point2; } public void MovePoints(int newX) // assignment to point1 has been removed { point2.X = newX; // Compliant: point2 is a class } } ---- == Resources === Documentation * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/readonly[readonly (C# Reference)] * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types[Reference types (C# reference)] * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-types[Value types (C# reference)] * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct[Structure types (C# reference)] ifdef::env-github,rspecator-view[] ''' == Implementation Specification (visible only on this page) === Message Restrict "x" to be a reference type or remove this assignment of "y"; it is useless if "x" is a value type. ''' == Comments And Links (visible only on this page) === on 13 May 2015, 20:13:12 Ann Campbell wrote: \[~tamas.vajk] * I've got the name of the equivalent R# rule, but I'm not sure how to find its key... * I suspect I may have missed some of the subtleties intended in this rule. Feel free to start an edit iteration === on 18 May 2015, 09:15:33 Tamas Vajk wrote: Updated the rule. Could you please check its language, and if it makes sense to you too? === on 21 May 2015, 14:34:22 Ann Campbell wrote: see what you think [~tamas.vajk] === on 22 May 2015, 11:28:16 Tamas Vajk wrote: Looks good, I adjusted some wording in the first sentence of the description === on 22 May 2015, 12:10:14 Ann Campbell wrote: Thanks [~tamas.vajk]. Looks good endif::env-github,rspecator-view[]