Skip to content

Commit 2b0e278

Browse files
authored
Use [NotNullWhen(true)] in more places (#47598)
* Use [NotNullWhen(true)] in more places Did a quick search/audit for methods that returned bool and took nullable object as the first input, and added [NotNullWhen(true)] where it was obviously correct. * Address PR feedback
1 parent 14453d6 commit 2b0e278

File tree

269 files changed

+716
-554
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

269 files changed

+716
-554
lines changed

docs/coding-guidelines/api-guidelines/nullability.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ The C# compiler respects a set of attributes that impact its flow analysis. We
9696
- **DO** annotate properties where a getter will never return `null` but a setter allows `null` as being non-nullable but also `[AllowNull]`.
9797
- **DO** annotate properties where a getter may return `null` but a setter throws for `null` as being nullable but also `[DisallowNull]`.
9898
- **DO** add `[NotNullWhen(true)]` to nullable arguments of `Try` methods that will definitively be non-`null` if the method returns `true`. For example, if `Int32.TryParse(string? s)` returns `true`, `s` is known to not be `null`, and so the method should be `public static bool TryParse([NotNullWhen(true)] string? s, out int result)`.
99+
- **DO** add `[NotNullWhen(true)]` to overrides of `public virtual bool Equals(object? obj)`, except in the extremely rare circumstance where a non-null instance may compare equally to `null` (one example of where it's not valid is on `Nullable<T>`).
99100
- **DO** add `[NotNullIfNotNull(string)]` if nullable ref argument will be non-`null` upon exit, when an other argument passed evaluated to non-`null`, pass that argument name as string. Example: `public void Exchange([NotNullIfNotNull("value")] ref object? location, object? value);`.
100101
- **DO** add `[return: NotNullIfNotNull(string)]` if a method would not return `null` in case an argument passed evaluated to non-`null`, pass that argument name as string. Example: `[return: NotNullIfNotNull("name")] public string? FormatName(string? name);`
101102
- **DO** add `[MemberNotNull(string fieldName)]` to a helper method which initializes member field(s), passing in the field name. Example: `[MemberNotNull("_buffer")] private void InitializeBuffer()`. This will help to avoid spurious warnings at call sites that call the initialization method and then proceed to use the specified field. Note that there are two constructors to `MemberNotNull`; one that takes a single `string`, and one that takes a `params string[]`. When the number of fields initialized is small (e.g. <= 3), it's preferable to use multiple `[MemberNotNull(string)]` attributes on the method rather than one `[MemberNotNull(string, string, string, ...)]` attribute, as the latter is not CLS compliant and will likely require `#pragma warning disable` and `#pragma warning restore` around the line to suppress warnings.

src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ protected Delegate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Al
9393
}
9494

9595

96-
public override bool Equals(object? obj)
96+
public override bool Equals([NotNullWhen(true)] object? obj)
9797
{
9898
if (obj == null || !InternalEqualTypes(this, obj))
9999
return false;

src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
**
1010
===========================================================*/
1111

12+
using System.Diagnostics.CodeAnalysis;
13+
1214
namespace System.Diagnostics.SymbolStore
1315
{
1416
internal struct SymbolToken
@@ -21,7 +23,7 @@ internal struct SymbolToken
2123

2224
public override int GetHashCode() { return m_token; }
2325

24-
public override bool Equals(object? obj)
26+
public override bool Equals([NotNullWhen(true)] object? obj)
2527
{
2628
if (obj is SymbolToken)
2729
return Equals((SymbolToken)obj);

src/coreclr/System.Private.CoreLib/src/System/Enum.CoreCLR.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics.CodeAnalysis;
45
using System.Reflection;
56
using System.Runtime.CompilerServices;
67
using System.Runtime.InteropServices;
@@ -13,7 +14,7 @@ public abstract partial class Enum
1314
private static extern void GetEnumValuesAndNames(QCallTypeHandle enumType, ObjectHandleOnStack values, ObjectHandleOnStack names, Interop.BOOL getNames);
1415

1516
[MethodImpl(MethodImplOptions.InternalCall)]
16-
public extern override bool Equals(object? obj);
17+
public extern override bool Equals([NotNullWhen(true)] object? obj);
1718

1819
[MethodImpl(MethodImplOptions.InternalCall)]
1920
private static extern object InternalBoxEnum(RuntimeType enumType, long value);

src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
5454

5555
// equals returns true IIF the delegate is not null and has the
5656
// same target, method and invocation list as this object
57-
public sealed override bool Equals(object? obj)
57+
public sealed override bool Equals([NotNullWhen(true)] object? obj)
5858
{
5959
if (obj == null)
6060
return false;

src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@ public override int GetHashCode()
12461246
return m_ptr != null ? m_ptr.GetHashCode() : 0;
12471247
}
12481248

1249-
public override bool Equals(object? obj)
1249+
public override bool Equals([NotNullWhen(true)] object? obj)
12501250
{
12511251
if (!(obj is ModuleHandle))
12521252
return false;

src/coreclr/System.Private.CoreLib/src/System/ValueType.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public abstract class ValueType
2222
{
2323
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
2424
Justification = "Trimmed fields don't make a difference for equality")]
25-
public override bool Equals(object? obj)
25+
public override bool Equals([NotNullWhen(true)] object? obj)
2626
{
2727
if (null == obj)
2828
{

src/libraries/System.Console/ref/System.Console.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ public enum ConsoleKey
310310
public char KeyChar { get { throw null; } }
311311
public System.ConsoleModifiers Modifiers { get { throw null; } }
312312
public bool Equals(System.ConsoleKeyInfo obj) { throw null; }
313-
public override bool Equals(object? value) { throw null; }
313+
public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; }
314314
public override int GetHashCode() { throw null; }
315315
public static bool operator ==(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) { throw null; }
316316
public static bool operator !=(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) { throw null; }

src/libraries/System.Console/src/System/ConsoleKeyInfo.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics.CodeAnalysis;
5+
46
namespace System
57
{
68
public readonly struct ConsoleKeyInfo : IEquatable<ConsoleKeyInfo>
@@ -46,7 +48,7 @@ public ConsoleModifiers Modifiers
4648
get { return _mods; }
4749
}
4850

49-
public override bool Equals(object? value)
51+
public override bool Equals([NotNullWhen(true)] object? value)
5052
{
5153
return value is ConsoleKeyInfo info && Equals(info);
5254
}

src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public void CopyTo(System.Span<byte> destination) { }
132132
public static System.Diagnostics.ActivitySpanId CreateFromUtf8String(System.ReadOnlySpan<byte> idData) { throw null; }
133133
public static System.Diagnostics.ActivitySpanId CreateRandom() { throw null; }
134134
public bool Equals(System.Diagnostics.ActivitySpanId spanId) { throw null; }
135-
public override bool Equals(object? obj) { throw null; }
135+
public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; }
136136
public override int GetHashCode() { throw null; }
137137
public static bool operator ==(System.Diagnostics.ActivitySpanId spanId1, System.Diagnostics.ActivitySpanId spandId2) { throw null; }
138138
public static bool operator !=(System.Diagnostics.ActivitySpanId spanId1, System.Diagnostics.ActivitySpanId spandId2) { throw null; }
@@ -171,7 +171,7 @@ public void CopyTo(System.Span<byte> destination) { }
171171
public static System.Diagnostics.ActivityTraceId CreateFromUtf8String(System.ReadOnlySpan<byte> idData) { throw null; }
172172
public static System.Diagnostics.ActivityTraceId CreateRandom() { throw null; }
173173
public bool Equals(System.Diagnostics.ActivityTraceId traceId) { throw null; }
174-
public override bool Equals(object? obj) { throw null; }
174+
public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; }
175175
public override int GetHashCode() { throw null; }
176176
public static bool operator ==(System.Diagnostics.ActivityTraceId traceId1, System.Diagnostics.ActivityTraceId traceId2) { throw null; }
177177
public static bool operator !=(System.Diagnostics.ActivityTraceId traceId1, System.Diagnostics.ActivityTraceId traceId2) { throw null; }
@@ -227,15 +227,15 @@ public readonly struct ActivityEvent
227227
public static bool operator ==(System.Diagnostics.ActivityContext left, System.Diagnostics.ActivityContext right) { throw null; }
228228
public static bool operator !=(System.Diagnostics.ActivityContext left, System.Diagnostics.ActivityContext right) { throw null; }
229229
public bool Equals(System.Diagnostics.ActivityContext value) { throw null; }
230-
public override bool Equals(object? obj) { throw null; }
230+
public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; }
231231
public override int GetHashCode() { throw null; }
232232
}
233233
public readonly struct ActivityLink : IEquatable<ActivityLink>
234234
{
235235
public ActivityLink(System.Diagnostics.ActivityContext context, System.Diagnostics.ActivityTagsCollection? tags = null) { throw null; }
236236
public System.Diagnostics.ActivityContext Context { get { throw null; } }
237237
public System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, object?>>? Tags { get { throw null; } }
238-
public override bool Equals(object? obj) { throw null; }
238+
public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; }
239239
public bool Equals(System.Diagnostics.ActivityLink value) { throw null; }
240240
public static bool operator ==(System.Diagnostics.ActivityLink left, System.Diagnostics.ActivityLink right) { throw null; }
241241
public static bool operator !=(System.Diagnostics.ActivityLink left, System.Diagnostics.ActivityLink right) { throw null; }

0 commit comments

Comments
 (0)