C# compiler strict mode

 
 
  • Gérald Barré

The C# compiler has some hidden features. Today I've discovered a new compiler option. The author of a recent issue on GitHub indicates that the C# compiler allows comparing an IntPtr with null, which at runtime is always false. He suggests the compiler should raise an error in this case. The answer of Sam Harwell describes a compiler option, /features:strict, to detect this error and a few other potential errors in your code.

To enable it, you must add <Features>strict</Features> to your csproj file:

XML
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <Features>strict</Features>
    <AnalysisLevel>latest</AnalysisLevel>
  </PropertyGroup>
</Project>

If your solution has many projects and you want to enable this compiler option for all projects, you can create a file named Directory.Build.props at the root of your solution with the content (MSBuild documentation):

csproj (MSBuild project file)
<Project>
  <PropertyGroup>
    <Features>strict</Features>
  </PropertyGroup>
</Project>

Here are some errors that will be reported by using this feature strict:

C#
IntPtr ptr = IntPtr.Zero;
if (ptr == null) // Warning CS8073 The result of the expression is always 'false' since a value of type 'IntPtr' is never equal to 'null' of type 'IntPtr?'
C#
lock (null) // Error CS0185 '<null>' is not a reference type as required by the lock statement
{
}
C#
var o = new object();
if (o is Math) // Error CS7023 The second operand of an 'is' or 'as' operator may not be static type 'Math'
{
}
C#
// In assembly A
public struct S
{
    private object _f;
}

// In assembly B
public class C
{
   void M()
   {
      S s; // Error CS0165: Use of unassigned local variable 's' (https://github.com/dotnet/roslyn/blob/master/docs/compilers/CSharp/Definite%20Assignment.md#definite-assignment-of-structs-across-assemblies)
   }
}
C#
enum Color { Black, Yellow, Red, White }
static void Bar()
{
    _ = 1 - Color.Red; // Error CS0019: Operator '-' cannot be applied to operands of type 'int' and 'Color'
}
C#
var func = new Func<string, string>(x => x);
_ = new Func<string, string>(ref func); // Error CS0149: Method name expected
C#
static void Demo(out ImmutableArray<string> result) // Error CS0177: The out parameter 'result' must be assigned to before control leaves the current method
{
}

// For more information: https://github.com/dotnet/roslyn/issues/13203

I hope this flag will be the default behavior in the next release of C#. Maybe they can enable it by default based on the language version of the project. But at the moment you must enable it manually…

Note that this flag is not documented and not well-known. After the comment on GitHub, the CoreCLR has started a new pull request to use this option in their codebase (Fix invalid IntPtr == null comparisons, set strict mode for Roslyn). It also helps in detecting issues in PowerShell Core.

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub