ILSpy icon indicating copy to clipboard operation
ILSpy copied to clipboard

Decompiled C# code should set [AllowNull] on properties instead of on setter

Open meziantou opened this issue 4 years ago • 2 comments

Input code

#nullable enable
class Sample
{
    [AllowNull]
    public string MyProperty { get; set; }
}

Erroneous output

using System.Diagnostics.CodeAnalysis;

internal class Sample
{
	public string MyProperty
	{
		get;
		[param: AllowNull]
		set;
	}
}

When you compile this code, the compiler complains with the following warning:

Warning CS8618 Non-nullable property 'MyProperty' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Details

  • Product in use: ILSpy
  • Version in use: 6.2.0.6062-preview1

meziantou avatar Sep 18 '20 04:09 meziantou

[AllowNull] is a normal custom attribute. ILSpy is displaying it correctly; it seems that the C# compiler for some reason moves this attribute to the setter???

dgrunwald avatar Sep 22 '20 06:09 dgrunwald

Indeed, the compiler move it to the setter (sharplab). This make sense as the attribute change the behavior of the value parameter (so only the setter). However, it seems not possible to define it directly on the setter... (maybe I should open an issue on the Roslyn repository)

When decompiling IL to C#, I think [AllowNull] / [DisallowNull] attributes should be moved back to the property.

meziantou avatar Sep 22 '20 14:09 meziantou

However, it seems not possible to define it directly on the setter... (maybe I should open an issue on the Roslyn repository)

If you use [param: System.Diagnostics.CodeAnalysis.AllowNull] it is possible.

When decompiling IL to C#, I think [AllowNull] / [DisallowNull] attributes should be moved back to the property.

I am not sure there is a sensible way to do this, as the following is already valid C# code:

public class A
{
    public string B
    {
        get;
        [param: System.Diagnostics.CodeAnalysis.AllowNull]
        set;
    }
}

And so is:

public class A
{
    [System.Diagnostics.CodeAnalysis.AllowNull]
    public string B
    {
        get;
        set;
    }
}

And both produce the exact same IL. I think, ILSpy should stay close to what's defined in the IL. Because I think there is nothing we can do at this point, I am going to close this.

If you or anybody else, thinks there is still something to discuss, please feel free to comment, or reopen/create a new issue referencing this one. Thanks!

siegfriedpammer avatar Oct 12 '22 10:10 siegfriedpammer