-
Notifications
You must be signed in to change notification settings - Fork 222
/
SynchronizedFieldAssignment.cs
151 lines (121 loc) · 5.6 KB
/
SynchronizedFieldAssignment.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Security.Cryptography.X509Certificates;
using System.Linq;
class Test
{
static readonly object staticReadonlyField = null;
static object staticReadWriteField = null;
readonly object readonlyField = null;
readonly string readonlyStringField = "a string";
object readWriteField = null;
static object StaticReadonlyProperty => null;
object ReadonlyProperty => null;
static object StaticReadWriteProperty { get; set; }
object ReadWriteProperty { get; set; }
void OnAStaticField()
{
lock (staticReadonlyField) { }
lock (staticReadWriteField) { } // Noncompliant {{'staticReadWriteField' is not 'readonly', and should not be used for synchronization.}}
// ^^^^^^^^^^^^^^^^^^^^
lock (Test.staticReadonlyField) { }
lock (Test.staticReadWriteField) { } // Noncompliant {{'staticReadWriteField' is not 'readonly', and should not be used for synchronization.}}
// ^^^^^^^^^^^^^^^^^^^^^^^^^
lock (AnotherClass.staticReadonlyField) { }
lock (AnotherClass.staticReadWriteField) { } // Noncompliant {{'staticReadWriteField' is not 'readonly', and should not be used for synchronization.}}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
void OnAFieldOfSameInstance()
{
lock (readonlyField) { }
lock (readonlyStringField) { }
lock (readWriteField) { } // Noncompliant {{'readWriteField' is not 'readonly', and should not be used for synchronization.}}
lock (this.readonlyField) { }
lock (this.readWriteField) { } // Noncompliant {{'readWriteField' is not 'readonly', and should not be used for synchronization.}}
}
void OnAFieldOfDifferentInstance()
{
var anotherInstance = new Test();
lock (anotherInstance.readonlyField) { }
lock (anotherInstance.readWriteField) { } // Noncompliant {{'readWriteField' is not 'readonly', and should not be used for synchronization.}}
lock (anotherInstance.readonlyField) { }
}
void OnALocalVariable()
{
object localVarNull = null;
lock (localVarNull) { } // Noncompliant {{'localVarNull' is a local variable, and should not be used for synchronization.}}
object localVarReadonlyField = readonlyField;
lock (localVarReadonlyField) { } // Noncompliant, while the local variable references a readonly field, the local variable itself can mutate
object localVarReadWriteField = readWriteField;
lock (localVarReadWriteField) { } // Noncompliant
}
void OnANewInstance()
{
lock (new object()) { } // Noncompliant {{Synchronizing on a new instance is a no-op.}}
lock (new ANamespace.AClass()) { } // Noncompliant
lock (new Test[] { }) // Noncompliant
lock (new[] { readonlyField}) { } // Noncompliant
lock (new Tuple<object>(readonlyField)) { } // Noncompliant
lock (new { }) // Noncompliant
lock ("a string") { } // Noncompliant
lock ($"an interpolated {"string"}") { } // Noncompliant
lock (1) { } // Error [CS0185]
lock ((a: readonlyField, b: readonlyField)) { } // Error [CS0185]
lock (new ADelegate(x => x)) { } // Noncompliant
lock (new Func<int, int>(x => x)) { } // Noncompliant
lock (x => x) { } // Error [CS0185]
lock ((int?)1) { } // Error [CS0185]
lock (from x in new object[2] select x) { } // Noncompliant
}
void OnAssignment()
{
object x;
lock (x = readonlyField) { }
lock (x = readWriteField) { } // FN, assignment not supported
}
void OtherCases(object oPar, bool bPar)
{
lock (null) { }
lock (oPar) { }
lock (this) { }
lock (SomeMethod()) { }
lock (oPar.GetType()) { }
lock (typeof(Test)) { }
lock (default(Test)) { }
object SomeMethod() => null;
lock (StaticReadonlyProperty) { }
lock (ReadonlyProperty) { }
lock (StaticReadWriteProperty) { }
lock (ReadWriteProperty) { }
lock (bPar ? readWriteField : readonlyField) { }
lock (oPar ?? readonlyField) { }
lock (oPar = readonlyField) { }
}
void ReadWriteReferences()
{
lock (RefReturnReadWriteField(this)) { } // FN, the method returns a readwrite ref to a member
lock (RefReturnStaticReadonlyField(this)) { } // FN, the method returns a readwrite ref to a member
ref object RefReturnReadWriteField(Test instance) => ref instance.readWriteField;
ref object RefReturnStaticReadonlyField(Test instance) => ref Test.staticReadWriteField;
}
delegate object ADelegate(object oPar);
}
class TestExplicitCast
{
readonly object readonlyField = null;
void Test()
{
lock ((AnotherClass)readonlyField) { } // Compliant, the cast operator can build
}
}
class AnotherClass
{
public static readonly object staticReadonlyField = null;
public static object staticReadWriteField = null;
public readonly object readonlyField = null;
public object readWriteField = null;
public static explicit operator AnotherClass(Test o) => new AnotherClass();
}
namespace ANamespace
{
class AClass { }
}