122 lines
3.7 KiB
Plaintext
122 lines
3.7 KiB
Plaintext
== 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<T1, T2>
|
|
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<T1, T2>
|
|
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[]
|