diff --git a/docs/fundamentals/code-analysis/overview.md b/docs/fundamentals/code-analysis/overview.md index 5867a1ac35513..406631417329e 100644 --- a/docs/fundamentals/code-analysis/overview.md +++ b/docs/fundamentals/code-analysis/overview.md @@ -58,6 +58,7 @@ The following rules are enabled, by default, as errors or warnings in .NET 10. A | [CA2261](quality-rules/ca2261.md) | Usage | Warning | .NET 8 | Do not use `ConfigureAwaitOptions.SuppressThrowing` with `Task` | | [CA2264](quality-rules/ca2264.md) | Usage | Warning | .NET 9 | Do not pass a non-nullable value to `ArgumentNullException.ThrowIfNull` | | [CA2265](quality-rules/ca2265.md) | Usage | Warning | .NET 9 | Do not compare `Span` to `null` or `default` | +| [CA2266](quality-rules/ca2266.md) | Usage | Warning | .NET 10 | File-based program entry point should start with `#!` | # [.NET 9](#tab/net-9) diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2266.md b/docs/fundamentals/code-analysis/quality-rules/ca2266.md new file mode 100644 index 0000000000000..510bee500c6a5 --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/ca2266.md @@ -0,0 +1,95 @@ +--- +title: "CA2266: File-based program entry point should start with '#!'" +description: "Learn about code analysis rule CA2266 - File-based program entry point should start with '#!'" +ms.date: 05/21/2026 +f1_keywords: + - CA2266 +helpviewer_keywords: + - CA2266 +dev_langs: + - CSharp +ai-usage: ai-assisted +--- + +# CA2266: File-based program entry point should start with `#!` + +| Property | Value | +|-------------------------------------|----------------------------------------------------| +| **Rule ID** | CA2266 | +| **Title** | File-based program entry point should start with `#!` | +| **Category** | [Usage](usage-warnings.md) | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default in .NET 10** | As warning | +| **Applicable languages** | C# | + +## Cause + +Your entry point file in a multi-file file-based program doesn't start with a shebang (`#!`) line. + +## Rule description + +For correct tool identification and direct shell execution support, start the entry point file with a shebang (`#!`) line to clearly distinguish it from files brought in with `#:include`. + +## How to fix violations + +Add a shebang line to the beginning of the entry point file, for example, `#!/usr/bin/env dotnet`. + +## Example + +The following code snippet shows a violation of CA2266. + +In `app.cs`: + +```csharp +#:include "helpers.cs" + +Console.WriteLine(GetMessage()); +``` + +In `helpers.cs`: + +```csharp +string GetMessage() => "Hello"; +``` + +The following code snippet fixes the violation. + +In `app.cs`: + +```csharp +#!/usr/bin/env dotnet +#:include "helpers.cs" + +Console.WriteLine(GetMessage()); +``` + +In `helpers.cs`: + +```csharp +string GetMessage() => "Hello"; +``` + +## When to suppress warnings + +If you intentionally omit the shebang line and have confirmed that your tooling can still identify the entry point correctly, it is safe to suppress this warning. + +## Suppress a warning + +For file-based apps, suppress a single violation by adding a `#:property` directive to the entry point file. + +```csharp +#:property NoWarn=$(NoWarn);CA2266 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.cs] +dotnet_diagnostic.CA2266.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../suppress-warnings.md). + +## See also + +[File-based apps](../../../core/sdk/file-based-apps.md#shell-execution) diff --git a/docs/fundamentals/code-analysis/quality-rules/index.md b/docs/fundamentals/code-analysis/quality-rules/index.md index e88df83dcf8d9..3fae2300fdc03 100644 --- a/docs/fundamentals/code-analysis/quality-rules/index.md +++ b/docs/fundamentals/code-analysis/quality-rules/index.md @@ -249,6 +249,7 @@ The following table lists code quality analysis rules. > | [CA2263: Prefer generic overload when type is known](ca2263.md) | Using a generic overload is preferable to passing a argument when the type is known, because they promote cleaner and more type-safe code with improved compile-time checks. | > | [CA2264: Do not pass a non-nullable value to `ArgumentNullException.ThrowIfNull`](ca2264.md) | `ArgumentNullException.ThrowIfNull` throws when the passed argument is `null`. Certain constructs like non-nullable structs, and `nameof()` and `new` expressions are known to never be null, so `ArgumentNullException.ThrowIfNull` will never throw. | > | [CA2265: Do not compare `Span` to `null` or `default`](ca2265.md) | Comparing a span to `null` or `default` might not do what you intended. `default` and the `null` literal are implicitly converted to `Span.Empty`. | +> | [CA2266: File-based program entry point should start with `#!`](ca2266.md) | When a file-based program consists of multiple files, the entry point file should start with a shebang (`#!`) line to clearly distinguish it from other included files. | > | [CA2300: Do not use insecure deserializer BinaryFormatter](ca2300.md) | Insecure deserializers are vulnerable when deserializing untrusted data. An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. | > | [CA2301: Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder](ca2301.md) | Insecure deserializers are vulnerable when deserializing untrusted data. An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. | > | [CA2302: Ensure BinaryFormatter.Binder is set before calling BinaryFormatter.Deserialize](ca2302.md) | Insecure deserializers are vulnerable when deserializing untrusted data. An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. | diff --git a/docs/fundamentals/code-analysis/quality-rules/usage-warnings.md b/docs/fundamentals/code-analysis/quality-rules/usage-warnings.md index 39ab1b3132689..dd60df7442bf5 100644 --- a/docs/fundamentals/code-analysis/quality-rules/usage-warnings.md +++ b/docs/fundamentals/code-analysis/quality-rules/usage-warnings.md @@ -62,6 +62,7 @@ Usage rules support proper usage of .NET. | [CA2260: Implement generic math interfaces correctly](ca2260.md) | Generic math interfaces require the derived type itself to be used for the self-recurring type parameter. | | [CA2261: Do not use `ConfigureAwaitOptions.SuppressThrowing` with `Task`](ca2261.md) | The `ConfigureAwaitOptions.SuppressThrowing` option isn't supported by the generic `Task`, since that might lead to returning an invalid `TResult`. | | [CA2262: Set `MaxResponseHeadersLength` properly](ca2262.md) | Make sure the `MaxResponseHeadersLength` value is provided correctly. This value is measured in kilobytes. | +| [CA2263: Prefer generic overload when type is known](ca2263.md) | Using a generic overload is preferable to passing a argument when the type is known, because they promote cleaner and more type-safe code with improved compile-time checks. | | [CA2264: Do not pass a non-nullable value to 'ArgumentNullException.ThrowIfNull'](ca2264.md) | 'ArgumentNullException.ThrowIfNull' throws when the passed argument is 'null'. Certain constructs like non-nullable structs, and 'nameof()' and 'new' expressions are known to never be null, so 'ArgumentNullException.ThrowIfNull' will never throw. | | [CA2265: Do not compare `Span` to `null` or `default`](ca2265.md) | Comparing a span to `null` or `default` might not do what you intended. `default` and the `null` literal are implicitly converted to `Span.Empty`. | -| [CA2263: Prefer generic overload when type is known](ca2263.md) | Using a generic overload is preferable to passing a argument when the type is known, because they promote cleaner and more type-safe code with improved compile-time checks. | +| [CA2266: File-based program entry point should start with `#!`](ca2266.md) | When a file-based program consists of multiple files, the entry point file should start with a shebang (`#!`) line to clearly distinguish it from other included files. | diff --git a/docs/navigate/tools-diagnostics/toc.yml b/docs/navigate/tools-diagnostics/toc.yml index 5cb6258113bc3..cdb2ae2d8caa0 100644 --- a/docs/navigate/tools-diagnostics/toc.yml +++ b/docs/navigate/tools-diagnostics/toc.yml @@ -3674,6 +3674,8 @@ items: href: ../../fundamentals/code-analysis/quality-rules/ca2264.md - name: CA2265 href: ../../fundamentals/code-analysis/quality-rules/ca2265.md + - name: CA2266 + href: ../../fundamentals/code-analysis/quality-rules/ca2266.md - name: Code style rules items: - name: Overview