Repository: nunit/nunit (2026-07-18T08:38:12Z)

Issue:
Use ArgumentNullException throw helper and remove CA1510 diagnostic
There's currently around 14 instances of this build diagnostic. It suggests moving away from explicit null check + throw code and instead towards using `ArgumentNullException.ThrowIfNull` due to performance reasons. That helper is built into .NET and a polyfill already exists within the framework to allow us to also use it on .NET Framework. This means we should be able to fix all instances of this fairly easily.

Ex: https://github.com/nunit/nunit/blob/2a011e013fbad0951b8172553f88d71a92a84c62/src/NUnitFramework/framework/Internal/PropertyBag.cs#L32

After fixing all cases we should also update the `.editorconfig` to include this line so that future cases will be caught. This will allow future instances to surface as warnings within an IDE such as Visual Studio, which then get escalated into errors by our build process.

```
dotnet_diagnostic.CA1510.severity = warning
```

Diagnostic info:   https://learn.microsoft.com/nb-no/dotnet/fundamentals/code-analysis/quality-rules/ca1510 

A current list of instances is below. The occurrences in tests might need to be case-by-cased for if inline suppression is better.
Code | Projects | Location | Line Number
-- | -- | -- | -- |
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\CommandLineOptions.cs | 35
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 358
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 610
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 645
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 678
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 696
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 711
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 726
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 744
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Options.cs | 828
CA1510 | nunitlite (net10.0), nunitlite (net8.0) | C:\repos\nunit\nunit\src\NUnitFramework\nunitlite\Tokenizer.cs | 101
CA1510 | nunit.framework.tests (net10.0), nunit.framework.tests (net8.0), nunit.framework.tests (net9.0) | C:\repos\nunit\nunit\src\NUnitFramework\tests\Extensions.cs | 18
CA1510 | nunit.framework.tests (net10.0), nunit.framework.tests (net8.0), nunit.framework.tests (net9.0) | C:\repos\nunit\nunit\src\NUnitFramework\tests\Syntax\ThrowsTests.cs | 163
CA1510 | nunit.framework.tests (net10.0), nunit.framework.tests (net8.0), nunit.framework.tests (net9.0) | C:\repos\nunit\nunit\src\NUnitFramework\tests\TestUtilities\StressUtility.cs | 14


Discussion:
@SinghAnsh07 Your [earlier PR](https://github.com/nunit/nunit/pull/5338) prompted a good discussion on the team about how it might be helpful to have a few `good first issue`s for these sort of things. Would you be interested in this one?
@stevenaw This seems like an enhancement I'd be interested in working upon. Could it be assigned to me?
@stevenaw yes! I would like to work on this.
Thanks @SinghAnsh07 !

@Shaurya2k06 Thanks for your interest as well! There is another scenario I can make an issue for if you'd like to contribute a fix for that
Sure! I'd be happy to give it a shot.



Patch:
diff --git a/.editorconfig b/.editorconfig
index 1168bd8385..19512013f9 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -142,6 +142,9 @@ csharp_style_expression_bodied_properties = when_on_single_line:suggestion
 # Microsofts own MemberNotNull attribute expects an array
 dotnet_diagnostic.CS3016.severity = none
 
+# CA1510: Use ArgumentNullException throw helper
+dotnet_diagnostic.CA1510.severity = warning
+
 ############################################################################################
 # IDE Analysis
 ############################################################################################
diff --git a/src/NUnitFramework/nunitlite/CommandLineOptions.cs b/src/NUnitFramework/nunitlite/CommandLineOptions.cs
index c8b8d9b77b..816c642256 100644
--- a/src/NUnitFramework/nunitlite/CommandLineOptions.cs
+++ b/src/NUnitFramework/nunitlite/CommandLineOptions.cs
@@ -32,8 +32,7 @@ public class CommandLineOptions : OptionSet
         internal CommandLineOptions(IDefaultOptionsProvider defaultOptionsProvider, bool requireInputFile, params string[] args)
         {
             // Apply default options
-            if (defaultOptionsProvider is null)
-                throw new ArgumentNullException(nameof(defaultOptionsProvider));
+            ArgumentNullException.ThrowIfNull(defaultOptionsProvider);
 
             TeamCity = defaultOptionsProvider.TeamCity;
 
diff --git a/src/NUnitFramework/nunitlite/Options.cs b/src/NUnitFramework/nunitlite/Options.cs
index e6ca4e4519..524ebb5f98 100644
--- a/src/NUnitFramework/nunitlite/Options.cs
+++ b/src/NUnitFramework/nunitlite/Options.cs
@@ -355,8 +355,7 @@ protected Option(string prototype, string description)
 
         protected Option(string prototype, string description, int maxValueCount)
         {
-            if (prototype is null)
-                throw new ArgumentNullException(nameof(prototype));
+            ArgumentNullException.ThrowIfNull(prototype);
             if (prototype.Length == 0)
                 throw new ArgumentException("Cannot be the empty string.", nameof(prototype));
             if (maxValueCount < 0)
@@ -607,8 +606,7 @@ public string MessageLocalizer(string msg)
 
         protected override string GetKeyForItem(Option item)
         {
-            if (item is null)
-                throw new ArgumentNullException(nameof(item));
+            ArgumentNullException.ThrowIfNull(item);
             if (item.Names is not null && item.Names.Length > 0)
                 return item.Names[0];
             // This should never happen, as it's invalid for Option to be
@@ -642,8 +640,7 @@ protected override void SetItem(int index, Option item)
 
         private void AddImpl(Option option)
         {
-            if (option is null)
-                throw new ArgumentNullException(nameof(option));
+            ArgumentNullException.ThrowIfNull(option);
             List<string> added = new List<string>(option.Names.Length);
             try
             {
@@ -675,8 +672,7 @@ private sealed class ActionOption : Option
             public ActionOption(string prototype, string description, int count, Action<OptionValueCollection> action)
                 : base(prototype, description, count)
             {
-                if (action is null)
-                    throw new ArgumentNullException(nameof(action));
+                ArgumentNullException.ThrowIfNull(action);
                 _action = action;
             }
 
@@ -693,8 +689,7 @@ public OptionSet Add(string prototype, Action<string> action)
 
         public OptionSet Add(string prototype, string description, Action<string> action)
         {
-            if (action is null)
-                throw new ArgumentNullException(nameof(action));
+            ArgumentNullException.ThrowIfNull(action);
             Option p = new ActionOption(prototype, description, 1,
                     delegate(OptionValueCollection v) { action(v[0]); });
             base.Add(p);
@@ -708,8 +703,7 @@ public OptionSet Add(string prototype, OptionAction<string, string> action)
 
         public OptionSet Add(string prototype, string description, OptionAction<string, string> action)
         {
-            if (action is null)
-                throw new ArgumentNullException(nameof(action));
+            ArgumentNullException.ThrowIfNull(action);
             Option p = new ActionOption(prototype, description, 2,
                     delegate(OptionValueCollection v) { action(v[0], v[1]); });
             base.Add(p);
@@ -723,8 +717,7 @@ private sealed class ActionOption<T> : Option
             public ActionOption(string prototype, string description, Action<T> action)
                 : base(prototype, description, 1)
             {
-                if (action is null)
-                    throw new ArgumentNullException(nameof(action));
+                ArgumentNullException.ThrowIfNull(action);
                 _action = action;
             }
 
@@ -741,8 +734,7 @@ private sealed class ActionOption<TKey, TValue> : Option
             public ActionOption(string prototype, string description, OptionAction<TKey, TValue> action)
                 : base(prototype, description, 2)
             {
-                if (action is null)
-                    throw new ArgumentNullException(nameof(action));
+                ArgumentNullException.ThrowIfNull(action);
                 _action = action;
             }
 
@@ -825,8 +817,7 @@ private static bool Unprocessed(ICollection<string> extra, Option def, OptionCon
 
         protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value)
         {
-            if (argument is null)
-                throw new ArgumentNullException(nameof(argument));
+            ArgumentNullException.ThrowIfNull(argument);
 
             flag = name = sep = value = null;
             Match m = ValueOption.Match(argument);
diff --git a/src/NUnitFramework/nunitlite/Tokenizer.cs b/src/NUnitFramework/nunitlite/Tokenizer.cs
index 1b589f5ce5..36e5d54ef6 100644
--- a/src/NUnitFramework/nunitlite/Tokenizer.cs
+++ b/src/NUnitFramework/nunitlite/Tokenizer.cs
@@ -98,8 +98,7 @@ public class Tokenizer
 
         public Tokenizer(string input)
         {
-            if (input is null)
-                throw new ArgumentNullException(nameof(input));
+            ArgumentNullException.ThrowIfNull(input);
 
             _input = input;
             _index = 0;


Test patch:
diff --git a/src/NUnitFramework/tests/Assertions/LowTrustFixture.cs b/src/NUnitFramework/tests/Assertions/LowTrustFixture.cs
index 473728ef06..626886c567 100644
--- a/src/NUnitFramework/tests/Assertions/LowTrustFixture.cs
+++ b/src/NUnitFramework/tests/Assertions/LowTrustFixture.cs
@@ -161,8 +161,7 @@ public void Run(Action action)
         }
         public object? Run(MethodInfo method, params object[] parameters)
         {
-            if (method is null)
-                throw new ArgumentNullException(nameof(method));
+            ArgumentNullException.ThrowIfNull(method);
             if (_appDomain is null)
                 throw new ObjectDisposedException(null);
 
diff --git a/src/NUnitFramework/tests/Extensions.cs b/src/NUnitFramework/tests/Extensions.cs
index 3073653ec3..6fd06b5a39 100644
--- a/src/NUnitFramework/tests/Extensions.cs
+++ b/src/NUnitFramework/tests/Extensions.cs
@@ -15,8 +15,7 @@ internal static class Extensions
         /// </summary>
         public static void AssertPassed(this ITestResult result)
         {
-            if (result is null)
-                throw new ArgumentNullException(nameof(result));
+            ArgumentNullException.ThrowIfNull(result);
 
             Assert.That(result.ResultState.Status, Is.EqualTo(TestStatus.Passed), result.Message);
         }
diff --git a/src/NUnitFramework/tests/Syntax/ThrowsTests.cs b/src/NUnitFramework/tests/Syntax/ThrowsTests.cs
index 77956f3b63..0c81b0a2f7 100644
--- a/src/NUnitFramework/tests/Syntax/ThrowsTests.cs
+++ b/src/NUnitFramework/tests/Syntax/ThrowsTests.cs
@@ -160,8 +160,10 @@ internal class MyClass
         {
             public MyClass(string s)
             {
+#pragma warning disable CA1510 // Use ArgumentNullException throw helper -- Intentionally parameterless for test assertions
                 if (s is null)
                     throw new ArgumentNullException();
+#pragma warning restore CA1510
             }
         }
     }
diff --git a/src/NUnitFramework/tests/TestUtilities/StressUtility.cs b/src/NUnitFramework/tests/TestUtilities/StressUtility.cs
index ecc52cabc8..057903751f 100644
--- a/src/NUnitFramework/tests/TestUtilities/StressUtility.cs
+++ b/src/NUnitFramework/tests/TestUtilities/StressUtility.cs
@@ -11,8 +11,7 @@ public static class StressUtility
     {
         public static void RunParallel(Action action, int times, int maxParallelism, bool useThreadPool = true)
         {
-            if (action is null)
-                throw new ArgumentNullException(nameof(action));
+            ArgumentNullException.ThrowIfNull(action);
             if (times < 0)
                 throw new ArgumentOutOfRangeException(nameof(times), times, "Number of times to run must be greater than or equal to 0.");
             if (maxParallelism < 1)