Skip to content

BRO1104: Use default instead of a value type's default constructor

new int() creates the default value; default(int) says so. Replaces StyleCop SA1129.

Example

Before

using System;
using System.Threading;

public class Scheduler
{
    public DateTime Start { get; set; } = new DateTime();

    public Guid Run(CancellationToken token = new CancellationToken())
    {
        return new Guid();
    }
}

After

using System;
using System.Threading;

public class Scheduler
{
    public DateTime Start { get; set; } = default(DateTime);

    public Guid Run(CancellationToken token = default(CancellationToken))
    {
        return Guid.Empty;
    }
}

Why

new DateTime() looks like it creates something meaningful, but it's just DateTime.MinValue, the all-zero default. Writing default(DateTime), or Guid.Empty, makes that explicit.

How the fix works

The same replacements as StyleCop:

Before After
new int(), new Point(), Point p = new(); default(int), default(Point), default(Point)
new CancellationToken() CancellationToken.None
new Guid() Guid.Empty
new IntPtr(), new UIntPtr() IntPtr.Zero, UIntPtr.Zero
new nint(), new nuint() default(nint), default(nuint)
new Color() for an enum with a zero member Red Color.Red

A parameter's default value must be a constant, so there new Guid() becomes default(Guid) instead of Guid.Empty, as in the example.

Configuration

The SDK's csharp_prefer_simple_default_expression (IDE0034's option) is followed when it is set to true (any severity suffix, such as true:warning): the fix writes the default literal instead of default(T). Unset or false keeps default(T), like StyleCop. The named replacements (Guid.Empty, CancellationToken.None, IntPtr.Zero, an enum's zero member) stay as they are.

[*.cs]
csharp_prefer_simple_default_expression = true
// Before
public DateTime Start { get; set; } = new DateTime();
public void Run(CancellationToken token = new CancellationToken()) { }
var count = new int();

// After
public DateTime Start { get; set; } = default;
public void Run(CancellationToken token = default) { }
var count = default(int);

The literal is written only where it means the same, checked by binding the statement again with it: var has no type for it, a conversion would change the value (object o = new int() boxes a zero, object o = default is null; int? n = default is null), an overload may no longer be picked, and a member access on it doesn't compile. Those keep default(T). All creations and default(T) expressions of one statement, initializer or expression body are checked together, since each alone may bind where all together don't (M(default, default) can be ambiguous). The literal needs C# 7.1; in a multi-targeted project the lowest language version of its target frameworks counts. With IDE0034 on as well, dotnet format converges in one run: before, new T() became default(T) and IDE0034 needed a second run to simplify it.

Not reported

  • Structs with their own parameterless constructor (C# 10 and later). new S() runs that constructor; default(S) doesn't. Like StyleCop.
  • new T() for a type parameter (where T : struct). If T has a parameterless constructor, new T() runs it and default(T) doesn't.
  • new S(); as a statement on its own. default(S); doesn't compile.
  • Creations with an initializer, even an empty one (new Point() { }), like StyleCop.
  • Creations with a comment inside (new Guid(/* none */)): the replacement would drop it.

Compared with StyleCop

nint/nuint always become default(nint)/default(nuint). StyleCop 1.2.0-beta.556 always writes nint.Zero, which doesn't compile (CS0117) before C# 11 or on runtimes without numeric IntPtr (.NET Framework, .NET Standard, .NET 6). StyleCop's master (unreleased) writes nint.Zero only where it compiles, but a multi-targeted project analyzes each file once per target framework: for net462;net8.0 the two copies would get different fixes, and the net462 build would break. default(nint) means the same and compiles everywhere. StyleCop also replaces new T() for type parameters, and turns new S(); into default(S);, which doesn't compile.