'Attributes on C#9 top level statements file

I'm trying to add attributes to a top-level statements file, and I'm not finding anything about it. Is it possible?

For some context: I want to disable a rule only in that file with:

[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:ElementsMustBeSeparatedByBlankLine", Justification = "Reviewed.")]

It's a rule with a known bug in top-level statements.

Is there any way?



Solution 1:[1]

Assuming you want to set an assembly-wide attribute, then it's the same as it was before C# 9.0. You're missing the assembly: keyword.

https://docs.microsoft.com/en-us/dotnet/standard/assembly/set-attributes

Change your code to add the assembly: keyword, like so:

[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:ElementsMustBeSeparatedByBlankLine", Justification = "Reviewed.")

If you want to add the attribute to the implicit entrypoint method (aka Program.Main) or its parent type class Program then you cannot, simply because C# 9.0's top-level-statements design does not allow programs to name or reference the method at all.

This is mentioned, briefly, in the documentation on top-level methods (emphasis mine):

https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements#implicit-entry-point-method

Implicit entry point method

The compiler generates a method to serve as the program entry point for a project with top-level statements. The name of this method isn't actually Main, it's an implementation detail that your code can't reference directly. The signature of the method depends on whether the top-level statements contain the await keyword or the return statement.

...in which case you'll need to change your code back to using a traditional explicit Main method:

[SuppressMessage("SomeClassRule", "", Justification = "It's my computer")]
public static class Program
{
    [SuppressMessage("SomeMethodRule", "", Justification = "It's my computer")]
    public static async Task<Int32> Main( String[] args )
    {
        return 0;
    }
}

However..., as you're wanting to use [SuppressMessage] on the Main method to suppress StyleCop warnings, you need to be made-aware of the fact that StyleCop (as with other static-analysis tools in .NET) now respect .editorconfig and #pragma warning disable|restore to suppress or disable warnings and checks.

Here's a quick comparison of #pragma vs [SuppressMessage]: when a technique has a "better" feature it's marked in bold:

#pragma warning disable [SuppressMessage]
Compiled into output assembly, growing your DLL size from all the constant strings and potentially exposing internal development details to external users No Yes
Explicit Justification field No

But you can add an explanatory comment on the same line.
Yes
Explicit target field for disambiguation No Yes
Requires modern versions of Visual Studio (2017 or 2019+) Yes No
Granularity Source code line

But if the same warning appears 2 or more times on the same source code line you cannot disambiguate
Discrete .NET assembly objects (types, parameters, fields, etc - but not per-line)

Solution 2:[2]

I had a similar issue with the [ExcludeFromCodeCoverage] attribute I wanted to use and received an answer for C# 10 that works. So if you able to migrate to C# 10 you can do the following with a partial class:

Create a Program.Attributes.cs (I named it that way, so it is nested under the Program.cs) with the following code:

[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:ElementsMustBeSeparatedByBlankLine", Justification = "Reviewed.")]
public static partial class Program { }

See the original answer here: https://stackoverflow.com/a/72013001/1099519

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2