From fdea82fcfe24ca49eb8c7cbeb82f705c42142292 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Mon, 10 Nov 2025 07:39:49 -0800 Subject: [PATCH 1/4] Update APIs that always throw on .NET (#49682) --- .../cryptography/10.0/openssl-macos-unsupported.md | 4 ++-- docs/core/compatibility/unsupported-apis.md | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/core/compatibility/cryptography/10.0/openssl-macos-unsupported.md b/docs/core/compatibility/cryptography/10.0/openssl-macos-unsupported.md index e40080bb5947e..fc223ec6c668d 100644 --- a/docs/core/compatibility/cryptography/10.0/openssl-macos-unsupported.md +++ b/docs/core/compatibility/cryptography/10.0/openssl-macos-unsupported.md @@ -1,11 +1,11 @@ --- -title: "Breaking change: OpenSSL cryptographic primitives aren't supported on macOS" +title: "Breaking change: OpenSSL cryptographic primitives not supported on macOS" description: "Learn about the breaking change in .NET 10 where OpenSSL cryptographic primitives are no longer supported on macOS." ms.date: 06/23/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/46789 --- -# OpenSSL cryptographic primitives are not supported on macOS +# OpenSSL cryptographic primitives not supported on macOS Starting in .NET 10, OpenSSL-backed cryptographic primitives are no longer supported on macOS. and classes that are specific to OpenSSL, such as , now throw a on macOS. diff --git a/docs/core/compatibility/unsupported-apis.md b/docs/core/compatibility/unsupported-apis.md index 36b703f05db71..864b69782a092 100644 --- a/docs/core/compatibility/unsupported-apis.md +++ b/docs/core/compatibility/unsupported-apis.md @@ -2,11 +2,11 @@ title: Unsupported APIs on .NET Core and .NET 5+ titleSuffix: "" description: Learn which .NET APIs always throw an exception on .NET Core and .NET 5 and later versions. -ms.date: 09/08/2025 +ms.date: 11/07/2025 --- -# APIs that always throw exceptions on .NET Core and .NET 5+ +# APIs that always throw exceptions on .NET (Core) -The following APIs will always throw an exception on .NET (Core) on all or a subset of platforms. In most cases, the exception that's thrown is . +The following APIs always throw an exception on .NET (Core) on all or a subset of platforms. In most cases, the exception that's thrown is . This article organizes the affected APIs by namespace. @@ -242,6 +242,7 @@ This article organizes the affected APIs by namespace. | Member | Platforms that throw | |--------|----------------------| +| | macOS | | | All | | | Linux and macOS | | | Linux and macOS | @@ -264,14 +265,17 @@ This article organizes the affected APIs by namespace. | | Linux and macOS | | | Linux and macOS | | | Linux and macOS | +| | macOS | | | All | | | All | | | All | | | All | +| | macOS | | | Linux and macOS | | | All | | | All | | | All | +| | macOS | | | All | | | All | | | All | @@ -284,10 +288,12 @@ This article organizes the affected APIs by namespace. | | Linux and macOS | | | All | | | All | +| | macOS | | | All | | | All | | | All | | | All | +| | macOS | | | All | | | All | From 54464add445230cd200376d260bffa559bd7e568 Mon Sep 17 00:00:00 2001 From: Adam Boniecki <20281641+abonie@users.noreply.github.com> Date: Mon, 10 Nov 2025 17:03:36 +0100 Subject: [PATCH 2/4] What's new in F# 10 (#49649) * What's new in F# 10 * Add ai-usage metadata * Add link in .net 10 overview to F# * Apply suggestions from code review Co-authored-by: Adam Boniecki <20281641+abonie@users.noreply.github.com> * Add links to language reference * Add entries about *Final methods to CE reference * Update parameters page with voption for optional param info * Apply review feedback * Add type cache section * Add Whats New F#10 to the ToC --------- Co-authored-by: Bill Wagner --- docs/core/whats-new/dotnet-10/overview.md | 2 +- docs/fsharp/index.yml | 2 + .../computation-expressions.md | 2 + .../parameters-and-arguments.md | 12 + docs/fsharp/toc.yml | 2 + docs/fsharp/whats-new/fsharp-10.md | 401 ++++++++++++++++++ 6 files changed, 420 insertions(+), 1 deletion(-) create mode 100644 docs/fsharp/whats-new/fsharp-10.md diff --git a/docs/core/whats-new/dotnet-10/overview.md b/docs/core/whats-new/dotnet-10/overview.md index 1ffca77d92077..bbb8b42c6e51e 100644 --- a/docs/core/whats-new/dotnet-10/overview.md +++ b/docs/core/whats-new/dotnet-10/overview.md @@ -75,7 +75,7 @@ The F# updates in .NET 10 include several new features and improvements across t General improvements and bug fixes in the compiler implementation. -For more information, see the [F# release notes](https://fsharp.github.io/fsharp-compiler-docs/release-notes/About.html). +For more information, see [What's new in F# 10](../../../fsharp/whats-new/fsharp-10.md) or the [F# release notes](https://fsharp.github.io/fsharp-compiler-docs/release-notes/About.html). ## Visual Basic diff --git a/docs/fsharp/index.yml b/docs/fsharp/index.yml index 8480d506db697..2219fb6212cdc 100644 --- a/docs/fsharp/index.yml +++ b/docs/fsharp/index.yml @@ -120,6 +120,8 @@ landingContent: linkLists: - linkListType: whats-new links: + - text: "What's new in F# 10" + url: whats-new/fsharp-10.md - text: "What's new in F# 9" url: whats-new/fsharp-9.md - text: "What's new in F# 8" diff --git a/docs/fsharp/language-reference/computation-expressions.md b/docs/fsharp/language-reference/computation-expressions.md index 75d668b36d595..f3224cae1fcd4 100644 --- a/docs/fsharp/language-reference/computation-expressions.md +++ b/docs/fsharp/language-reference/computation-expressions.md @@ -264,6 +264,7 @@ The following table describes methods that can be used in a workflow builder cla |`Delay`|`(unit -> M<'T>) -> Delayed<'T>`|Wraps a computation expression as a function. `Delayed<'T>` can be any type, commonly `M<'T>` or `unit -> M<'T>` are used. The default implementation returns a `M<'T>`.| |`Return`|`'T -> M<'T>`|Called for `return` in computation expressions.| |`ReturnFrom`|`M<'T> -> M<'T>`|Called for `return!` in computation expressions.| +|`ReturnFromFinal`|`M<'T> -> M<'T>`|If present, called for `return!` and `do!` when in tail-call position.| |`BindReturn`|`(M<'T1> * ('T1 -> 'T2)) -> M<'T2>`|Called for an efficient `let! ... return` in computation expressions.| |`BindNReturn`|`(M<'T1> * M<'T2> * ... * M<'TN> * ('T1 * 'T2 ... * 'TN -> M<'U>)) -> M<'U>`|Called for efficient `let! ... and! ... return` in computation expressions without merging inputs.

for example, `Bind3Return`, `Bind4Return`.| |`MergeSources`|`(M<'T1> * M<'T2>) -> M<'T1 * 'T2>`|Called for `and!` in computation expressions.| @@ -277,6 +278,7 @@ The following table describes methods that can be used in a workflow builder cla |`While`|`(unit -> bool) * Delayed<'T> -> M<'T>`or

`(unit -> bool) * Delayed -> M`|Called for `while...do` expressions in computation expressions.| |`Yield`|`'T -> M<'T>`|Called for `yield` expressions in computation expressions.| |`YieldFrom`|`M<'T> -> M<'T>`|Called for `yield!` expressions in computation expressions.| +|`YieldFromFinal`|`M<'T> -> M<'T>`|If present, called for `yield!` when in tail-call position and in case of `do!` in tail-call position as a fallback for `ReturnFromFinal`| |`Zero`|`unit -> M<'T>`|Called for empty `else` branches of `if...then` expressions in computation expressions.| |`Quote`|`Quotations.Expr<'T> -> Quotations.Expr<'T>`|Indicates that the computation expression is passed to the `Run` member as a quotation. It translates all instances of a computation into a quotation.| diff --git a/docs/fsharp/language-reference/parameters-and-arguments.md b/docs/fsharp/language-reference/parameters-and-arguments.md index 7d0cf9bce6a2a..8bd34a52c5ac2 100644 --- a/docs/fsharp/language-reference/parameters-and-arguments.md +++ b/docs/fsharp/language-reference/parameters-and-arguments.md @@ -150,6 +150,18 @@ Baud Rate: 9600 Duplex: Full Parity: false Baud Rate: 4800 Duplex: Half Parity: false ``` +You can also specify an optional parameter to be a [Value Option](./value-options.md) type by applying a `[]` attribute to it. + +```fsharp +type T() = + static member M([] ?p : string) = + match p with + | ValueSome s -> printfn "%s" s + | ValueNone -> printfn "None" +``` + +When using struct-backed optional parameter, as seen above, you would use `defaultValueArg` instead of `defaultArg` to set the default value of the parameter. + ### Optional parameters (C# interop) For the purposes of C# interop, you can use the attributes `[]` in F#, so that callers will see an argument as optional. This is equivalent to defining the argument as optional in C# as in `MyMethod(int i = 3)`. This form was introduced in F# 4.1 to help facilitate interoperation with C# code. diff --git a/docs/fsharp/toc.yml b/docs/fsharp/toc.yml index 4572ae9e0f489..10152aed6f12f 100644 --- a/docs/fsharp/toc.yml +++ b/docs/fsharp/toc.yml @@ -292,6 +292,8 @@ items: href: tutorials/using-functions.md - name: What's new items: + - name: F# 10 + href: whats-new/fsharp-10.md - name: F# 9 href: whats-new/fsharp-9.md - name: F# 8 diff --git a/docs/fsharp/whats-new/fsharp-10.md b/docs/fsharp/whats-new/fsharp-10.md new file mode 100644 index 0000000000000..89f04310bb1e1 --- /dev/null +++ b/docs/fsharp/whats-new/fsharp-10.md @@ -0,0 +1,401 @@ +--- +title: What's new in F# 10 - F# Guide +description: Get an overview of the new features available in F# 10. +ms.date: 11/11/2025 +ms.topic: whats-new +ai-usage: ai-assisted +--- +# What's new in F# 10 + +F# 10 brings you several improvements to the F# language, FSharp.Core library, and tooling. +This version is a refinement release focused on clarity, consistency, and performance, with small but meaningful improvements that make your everyday code more legible and robust. +F# 10 ships with **.NET 10** and **Visual Studio 2026**. + +You can download the latest .NET SDK from the [.NET downloads page](https://dotnet.microsoft.com/download). + +## Get started + +F# 10 is available in all .NET Core distributions and Visual Studio tooling. +For more information, see [Get started with F#](../get-started/index.md). + +## Scoped warning suppression + +You can now suppress warnings in specific sections of your code using the new `#warnon` directive. +This pairs with the [existing `#nowarn` directive](../language-reference/compiler-directives.md#warn-directives) to give you precise control over which warnings apply where. + +Previously, when you used `#nowarn`, it would disable a warning for the remainder of the file, which could suppress legitimate issues elsewhere. +Let's look at a motivating example: + +```fsharp +// We know f is never called with None. +let f (Some a) = // creates warning 25, which we want to suppress + // 2000 loc, where the incomplete match warning is beneficial +``` + +If you add `#nowarn 25` above the function definition, it disables FS0025 for the entire remainder of the file. + +With F# 10, you can now mark the exact section where you want the warning suppressed: + +```fsharp +#nowarn 25 +let f (Some x) = // FS0025 suppressed +#warnon 25 + // FS0025 enabled again +``` + +Conversely, if a warning is disabled globally (for example, via a compiler flag), you can enable it locally with `#warnon`. +This directive will apply until a matching `#nowarn` or the end of the file. + +**Important compatibility notes:** + +This feature includes several changes that improve the consistency of `#nowarn`/`#warnon` directives. +These are breaking changes: + +* The compiler no longer allows multiline and empty warn directives. +* The compiler no longer allows whitespace between `#` and `nowarn`. +* You cannot use triple-quoted, interpolated, or verbatim strings for warning numbers. + +Script behavior has also changed. +Previously, when you added a `#nowarn` directive anywhere in a script, it applied to the whole compilation. +Now, its behavior in scripts matches that in `.fs` files, applying only until the end of the file or a corresponding `#warnon`. + +This feature implements [RFC FS-1146](https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1146-scoped-nowarn.md). + +## Access modifiers on auto property accessors + +A common pattern in object-oriented programming is to create publicly readable but privately mutable state. +Before F# 10, you needed explicit [property syntax](../language-reference/members/properties.md) with backing fields (hidden variables that store the actual property values) to achieve this, which added repetitive code: + +```fsharp +type Ledger() = + [] val mutable private _Balance: decimal + member this.Balance with public get() = this._Balance and private set v = this._Balance <- v +``` + +With F# 10, you can now apply different access modifiers to individual property accessors. +This lets you specify different access levels for the getter and setter of a property, making the pattern much simpler: + +```fsharp +type Ledger() = + member val Balance = 0m with public get, private set +``` + +You can place an access modifier either before the property name (applying to both accessors) or before individual accessors, but not both simultaneously. + +Note that this feature does not extend to signature (`.fsi`) files. +The correct signature for the `Ledger` example above is: + +```fsharp +type Ledger() = + member Balance : decimal + member private Balance : decimal with set +``` + +This feature implements [RFC FS-1141](https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1141-Allow-access-modifiers-to-auto-properties-getters-and-setters.md). + +## ValueOption optional parameters + +You can now use a struct-based [`ValueOption<'T>`](../language-reference/value-options.md) representation for [optional parameters](../language-reference/parameters-and-arguments.md#optional-parameters-f-native). +When you apply the `[]` attribute to an optional parameter, the compiler uses `ValueOption<'T>` instead of the reference-based `option` type. +This avoids heap allocations (memory allocated on the managed heap that requires garbage collection) for the option wrapper, which is beneficial in performance-critical code. + +Previously, F# always used the heap-allocated `option` type for optional parameters, even when the parameter was absent: + +```fsharp +// Prior to F# 10: always uses reference option +type X() = + static member M(?x : string) = + match x with + | Some v -> printfn "Some %s" v + | None -> printfn "None" +``` + +In F# 10, you can use the `[]` attribute to leverage the struct-backed `ValueOption`: + +```fsharp +type X() = + static member M([] ?x : string) = + match x with + | ValueSome v -> printfn "ValueSome %s" v + | ValueNone -> printfn "ValueNone" +``` + +This eliminates heap allocations when the argument is absent, which is beneficial in performance-critical code. + +Choose this struct-based option for small values or frequently constructed types where allocation pressure matters. +Use the default reference-based `option` when you rely on existing pattern matching helpers, need reference semantics, or when the performance difference is negligible. +This feature strengthens parity with other F# language constructs that already support `ValueOption`. + +## Tail-call support in computation expressions + +F# 10 adds [tail-call](../language-reference/functions/recursive-functions-the-rec-keyword.md#tail-recursion) optimizations for [computation expressions](../language-reference/computation-expressions.md). +Computation-expression builders can now opt into these optimizations by implementing special methods. + +When the compiler translates computation expressions into regular F# code (a process called desugaring), it recognizes when an expression like `return!`, `yield!`, or `do!` appears in a tail position. +If your builder provides the following methods, the compiler routes those calls to optimized entry points: + +* `ReturnFromFinal` - called for a tail `return!` (falls back to `ReturnFrom` if absent) +* `YieldFromFinal` - called for a tail `yield!` (falls back to `YieldFrom` if absent) +* For a terminal `do!`, the compiler prefers `ReturnFromFinal`, then `YieldFromFinal`, before falling back to the normal `Bind` pathway + +These `*Final` members are optional and exist purely to enable optimization. +Builders that do not provide these members keep their existing semantics unchanged. + +For example: + +```fsharp +coroutine { + yield! subRoutine() // tail position -> YieldFromFinal if available +} +``` + +However, in a non-tail position: + +```fsharp +coroutine { + try + yield! subRoutine() // not tail -> normal YieldFrom + finally () +} +``` + +**Important compatibility note:** + +This change can be breaking if a computation expression builder already defines members with these names. +In most cases, existing builders continue to work without modification when compiled with F# 10. +Older compilers will ignore the new `*Final` methods, so builders that must remain compatible with earlier compiler versions should not assume the compiler will invoke these methods. + +This feature implements [RFC FS-1330](https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1330-support-tailcalls-in-computation-expressions.md). + +## Typed bindings in computation expressions without parentheses + +F# 10 removes the requirement for parentheses when adding type annotations to computation expression bindings. +You can now add type annotations on `let!`, `use!`, and `and!` bindings using the same syntax as ordinary `let` bindings. + +Previously, you had to use parentheses for type annotations: + +```fsharp +async { + let! (a: int) = fetchA() + and! (b: int) = fetchB() + use! (d: MyDisposable) = acquireAsync() + return a + b +} +``` + +In F# 10, you can write type annotations without parentheses: + +```fsharp +async { + let! a: int = fetchA() + and! b: int = fetchB() + use! d: MyDisposable = acquireAsync() + return a + b +} +``` + +## Allow `_` in `use!` bindings + +You can now use the discard pattern (`_`) in `use!` bindings within computation expressions. +This aligns the behavior of `use!` with regular `use` bindings. + +Previously, the compiler rejected the discard pattern in `use!` bindings, forcing you to create throwaway identifiers: + +```fsharp +counterDisposable { + use! _ignored = new Disposable() + // logic +} +``` + +In F# 10, you can use the discard pattern directly: + +```fsharp +counterDisposable { + use! _ = new Disposable() + // logic +} +``` + +This clarifies intent when binding asynchronous resources whose values are only needed for lifetime management. + +## Rejecting pseudo-nested modules in types + +The compiler now raises an error when you place a `module` declaration indented at the same structural level inside a type definition. +This tightens structural validation to reject misleading module placement within types. + +Previously, the compiler accepted `module` declarations indented within type definitions, but it actually created these modules as siblings to the type rather than nesting them within it: + +```fsharp +type U = + | A + | B + module M = // Silently created a sibling module, not nested + let f () = () +``` + +With F# 10, this pattern raises error FS0058, forcing you to clarify your intent with proper module placement: + +```fsharp +type U = + | A + | B + +module M = + let f () = () +``` + +## Deprecation warning for omitted `seq` + +The compiler now warns you about bare sequence expressions that omit the `seq` builder. +When you use bare range braces like `{ 1..10 }`, you'll see a deprecation warning encouraging you to use the explicit `seq { ... }` form. + +Historically, F# allowed a special-case "sequence comprehension lite" syntax where you could omit the `seq` keyword: + +```fsharp +{ 1..10 } |> List.ofSeq // implicit sequence, warning FS3873 in F# 10 +``` + +In F# 10, the compiler warns about this pattern and encourages the explicit form: + +```fsharp +seq { 1..10 } |> List.ofSeq +``` + +This is currently a warning, not an error, giving you time to update your codebase. +If you want to suppress this warning, use the `NoWarn` property in your project file or `#nowarn` directive locally and pass it the warning number: 3873. + +The explicit `seq` form improves code clarity and consistency with other computation expressions. +Future versions of F# may make this an error, so we recommend adopting the explicit syntax when you update your code. + +This feature implements [RFC FS-1033](https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1033-Deprecate-places-where-seq-can-be-omitted.md). + +## Attribute target enforcement + +F# 10 enforces attribute target validation across all language constructs. +The compiler now validates that attributes are only applied to their intended targets by checking `AttributeTargets` across let-bound values, functions, union cases, implicit constructors, structs, and classes. + +Previously, the compiler silently allowed you to misapply attributes to incompatible targets. +This caused subtle bugs, such as test attributes being ignored when you forgot `()` to make a function: + +```fsharp +[] +let ``this is not a function`` = // Silently ignored in F# 9, not a test! + Assert.True(false) +``` + +In F# 10, the compiler enforces attribute targets and raises a warning when attributes are misapplied: + +```fsharp +[] +//^^^^ - warning FS0842: This attribute cannot be applied to property, field, return value. Valid targets are: method +let ``this is not a function`` = + Assert.True(false) +``` + +**Important compatibility note:** + +This is a breaking change that may reveal previously silent issues in your codebase. +The early errors prevent test discovery problems and ensure that attributes like analyzers and decorators take effect as intended. + +## Support for `and!` in task expressions + +You can now await multiple tasks concurrently using [`and!`](../language-reference/computation-expressions.md#and) in [task expressions](../language-reference/task-expressions.md). +Using `task` is a popular way to work with asynchronous workflows in F#, especially when you need interoperability with C#. +However, until now, there was no concise way to await multiple tasks concurrently in a computation expression. + +Perhaps you started with code that awaited computations sequentially: + +```fsharp +// Awaiting sequentially +task { + let! a = fetchA() + let! b = fetchB() + return combineAB a b +} +``` + +If you then wanted to change it to await them concurrently, you would typically use `Task.WhenAll`: + +```fsharp +// Use explicit Task combinator to await concurrently +task { + let ta = fetchA() + let tb = fetchB() + let! results = Task.WhenAll([| ta; tb |]) + return combineAB ta.Result tb.Result +} +``` + +In F# 10, you can use `and!` for a more idiomatic approach: + +```fsharp +task { + let! a = fetchA() + and! b = fetchB() + return combineAB a b +} +``` + +This combines the semantics of the concurrent version with the simplicity of the sequential version. + +This feature implements F# language suggestion [#1363](https://github.com/fsharp/fslang-suggestions/issues/1363), and it's implemented as an addition to the `FSharp.Core` library. +Most projects get the latest version of `FSharp.Core` automatically from the compiler, unless they explicitly pin a version. +In that case, you'll need to update it to use this feature. + +## Better trimming by default + +F# 10 removes a long-standing bit of friction with trimming F# assemblies. +Trimming is the process of removing unused code from your published application to reduce its size. +You no longer have to manually maintain an `ILLink.Substitutions.xml` file just to strip large F# metadata resource blobs (signature and optimization data that the compiler uses but your application doesn't need at runtime). + +When you publish with trimming enabled (`PublishTrimmed=true`), the F# build now automatically generates an embedded substitutions file that targets these tooling-only F# resources. + +Previously, you had to manually maintain this file to strip the metadata. +This added maintenance burden and was easy to forget. + +The result is smaller output by default, less repetitive code to maintain, and one fewer maintenance hazard. +If you need full manual control, you can still add your own substitutions file. +You can turn off the auto-generation with the `false` property. + +## Parallel compilation in preview + +An exciting update for F# users looking to reduce compilation times: the parallel compilation features are stabilizing. +Starting with .NET 10, three features: graph-based type checking, parallel IL code generation, and parallel optimization, are grouped together under the `ParallelCompilation` project property. + +F# 10 enables this setting by default for projects using `LangVersion=Preview`. +We plan to enable it for all projects in .NET 11. + +Be sure to give it a try and see if it speeds up your compilation. +To enable parallel compilation in F# 10: + +```xml + + true + false + +``` + +If you want to opt out while still enjoying other preview features, set `ParallelCompilation` to false: + +```xml + + Preview + false + +``` + +Parallel compilation can significantly reduce compilation times for projects with multiple files and dependencies. + +## Type subsumption cache + +The compiler now caches type relationship checks to speed up type inference and improve IDE performance, particularly when working with complex type hierarchies. +By storing and reusing results from previous subsumption checks, the compiler avoids redundant computations that previously slowed down compilation and IntelliSense. + +**Managing the cache:** + +In most cases, the type subsumption cache improves performance without any configuration. +However, if you experience increased memory footprint or increased CPU usage (due to cache maintenance workers), you can adjust the cache behavior: + +* To disable the cache entirely, set `9` in your project file to fall back to F# 9 behavior. +* To turn off asynchronous cache eviction (which increases thread pressure) and use synchronous eviction instead, set the `FSharp_CacheEvictionImmediate=1` environment variable. From 90e749fcd6c4d7f7d702755f2d33d914b6d8f021 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:46:26 +0000 Subject: [PATCH 3/4] Add documentation for IDE0360, IDE0370, and IDE0380 code style rules (#49681) --- .../code-analysis/style-rules/ide0360.md | 79 +++++++++++++++ .../code-analysis/style-rules/ide0370.md | 76 +++++++++++++++ .../code-analysis/style-rules/ide0380.md | 97 +++++++++++++++++++ .../code-analysis/style-rules/index.md | 3 + .../style-rules/language-rules.md | 8 +- docs/navigate/tools-diagnostics/toc.yml | 6 ++ 6 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 docs/fundamentals/code-analysis/style-rules/ide0360.md create mode 100644 docs/fundamentals/code-analysis/style-rules/ide0370.md create mode 100644 docs/fundamentals/code-analysis/style-rules/ide0380.md diff --git a/docs/fundamentals/code-analysis/style-rules/ide0360.md b/docs/fundamentals/code-analysis/style-rules/ide0360.md new file mode 100644 index 0000000000000..8e28ae61771be --- /dev/null +++ b/docs/fundamentals/code-analysis/style-rules/ide0360.md @@ -0,0 +1,79 @@ +--- +title: "IDE0360: Simplify property accessor" +description: "Learn about code analysis rule IDE0360: Simplify property accessor" +ms.date: 11/08/2025 +f1_keywords: +- IDE0360 +helpviewer_keywords: +- IDE0360 +dev_langs: +- CSharp +ai-usage: ai-assisted +--- +# Simplify property accessor (IDE0360) + +| Property | Value | +|--------------------------|-----------------------------------------------| +| **Rule ID** | IDE0360 | +| **Title** | Simplify property accessor | +| **Category** | Style | +| **Subcategory** | Language rules (expression-level preferences) | +| **Applicable languages** | C# 13+ | +| **Options** | `csharp_style_prefer_simple_property_accessors` | + +## Overview + +This rule flags places where a property accessor that directly accesses the `field` keyword (C# 13+) can be simplified. When a property accessor only returns `field` or assigns a value to `field`, it can be simplified to a simple auto-accessor. + +## Options + +Options specify the behavior that you want the rule to enforce. For information about configuring options, see [Option format](language-rules.md#option-format). + +### csharp_style_prefer_simple_property_accessors + +| Property | Value | Description | +|-------------------|-----------------------------------------------|-------------------| +| **Option name** | `csharp_style_prefer_simple_property_accessors` | | +| **Option values** | `true` | Prefer simplified property accessors | +| | `false` | Disables the rule | +| **Default option value** | `true` | | + +## Example + +```csharp +// Code with violations. +public int Prop +{ + get { return field; } + set { field = (value > 0) ? value : throw new ArgumentException(); } +} + +// Fixed code. +public int Prop { get; set; } +``` + +## Suppress a warning + +If you want to suppress only a single violation, add preprocessor directives to your source file to disable and then re-enable the rule. + +```csharp +#pragma warning disable IDE0360 +// The code that's violating the rule is on this line. +#pragma warning restore IDE0360 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.IDE0360.severity = none +``` + +To disable all of the code-style rules, set the severity for the category `Style` to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_analyzer_diagnostic.category-Style.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../suppress-warnings.md). diff --git a/docs/fundamentals/code-analysis/style-rules/ide0370.md b/docs/fundamentals/code-analysis/style-rules/ide0370.md new file mode 100644 index 0000000000000..020138eba0531 --- /dev/null +++ b/docs/fundamentals/code-analysis/style-rules/ide0370.md @@ -0,0 +1,76 @@ +--- +title: "IDE0370: Remove unnecessary suppression" +description: "Learn about code analysis rule IDE0370: Remove unnecessary suppression" +ms.date: 11/08/2025 +f1_keywords: +- IDE0370 +helpviewer_keywords: +- IDE0370 +dev_langs: +- CSharp +ai-usage: ai-assisted +--- +# Remove unnecessary suppression (IDE0370) + +| Property | Value | +|--------------------------|--------------------------------------------------| +| **Rule ID** | IDE0370 | +| **Title** | Remove unnecessary suppression | +| **Category** | Style | +| **Subcategory** | Unnecessary code rules (suppression preferences) | +| **Applicable languages** | C# | +| **Options** | None | + +## Overview + +This rule identifies unnecessary nullable warning suppressions using the [null-forgiving operator](../../../csharp/language-reference/operators/null-forgiving.md) (`!`). The null-forgiving operator tells the compiler that the value is not null, which suppresses warnings for nullable reference types. However, when the compiler can already determine that a value is not null, the null-forgiving operator is unnecessary and can be removed. + +## Example + +```csharp +// Code with violations. +#nullable enable + +void ProcessValue() +{ + List names = new()!; +} + +// Fixed code. +#nullable enable + +void ProcessValue() +{ + List names = new(); // No suppression needed. +} +``` + +## Suppress a warning + +If you want to suppress only a single violation, add preprocessor directives to your source file to disable and then re-enable the rule. + +```csharp +#pragma warning disable IDE0370 +// The code that's violating the rule is on this line. +#pragma warning restore IDE0370 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.IDE0370.severity = none +``` + +To disable all of the code-style rules, set the severity for the category `Style` to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_analyzer_diagnostic.category-Style.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../suppress-warnings.md). + +## See also + +- [Nullable reference types](../../../csharp/nullable-references.md) diff --git a/docs/fundamentals/code-analysis/style-rules/ide0380.md b/docs/fundamentals/code-analysis/style-rules/ide0380.md new file mode 100644 index 0000000000000..a42dc99114354 --- /dev/null +++ b/docs/fundamentals/code-analysis/style-rules/ide0380.md @@ -0,0 +1,97 @@ +--- +title: "IDE0380: Remove unnecessary 'unsafe' modifier" +description: "Learn about code analysis rule IDE0380: Remove unnecessary 'unsafe' modifier" +ms.date: 11/08/2025 +f1_keywords: +- IDE0380 +helpviewer_keywords: +- IDE0380 +dev_langs: +- CSharp +ai-usage: ai-assisted +--- +# Remove unnecessary `unsafe` modifier (IDE0380) + +| Property | Value | +|--------------------------|-----------------------------------------------| +| **Rule ID** | IDE0380 | +| **Title** | Remove unnecessary `unsafe` modifier | +| **Category** | Style | +| **Subcategory** | Unnecessary code rules (modifier preferences) | +| **Applicable languages** | C# | +| **Options** | None | + +## Overview + +This rule identifies code blocks, methods, types, or other declarations marked with the `unsafe` modifier that don't actually contain any unsafe operations. The `unsafe` modifier allows the use of pointers and other unsafe code features, but when those features aren't being used, the modifier is unnecessary and should be removed for code clarity. + +## Example + +```csharp +// Code with violations. + +// Unnecessary, no unsafe operations. +unsafe class MyClass +{ + public void Method() + { + var x = 5; + } +} + +// Unnecessary, no unsafe operations. +unsafe void ProcessData(int value) +{ + Console.WriteLine(value); +} + +// Fixed code. +class MyClass +{ + public void Method() + { + var x = 5; + } +} + +void ProcessData(int value) +{ + Console.WriteLine(value); +} + +// Example where 'unsafe' is needed. +unsafe class ValidUsage +{ + int* pointer; // Pointer type requires 'unsafe'. +} +``` + +## Suppress a warning + +If you want to suppress only a single violation, add preprocessor directives to your source file to disable and then re-enable the rule. + +```csharp +#pragma warning disable IDE0380 +// The code that's violating the rule is on this line. +#pragma warning restore IDE0380 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.IDE0380.severity = none +``` + +To disable all of the code-style rules, set the severity for the category `Style` to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_analyzer_diagnostic.category-Style.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../suppress-warnings.md). + +## See also + +- [Unsafe code, pointer types, and function pointers](../../../csharp/language-reference/unsafe-code.md) diff --git a/docs/fundamentals/code-analysis/style-rules/index.md b/docs/fundamentals/code-analysis/style-rules/index.md index fec923289f122..7060e750e061e 100644 --- a/docs/fundamentals/code-analysis/style-rules/index.md +++ b/docs/fundamentals/code-analysis/style-rules/index.md @@ -146,6 +146,9 @@ The following table list all the code-style rules by ID and [options](../code-st > | [IDE0330](ide0330.md) | Prefer 'System.Threading.Lock' | [csharp_prefer_system_threading_lock](ide0330.md#csharp_prefer_system_threading_lock) | > | [IDE0340](ide0340.md) | Use unbound generic type | [csharp_style_prefer_unbound_generic_type_in_nameof](ide0340.md#csharp_style_prefer_unbound_generic_type_in_nameof) | > | [IDE0350](ide0350.md) | Use implicitly typed lambda | [csharp_style_prefer_implicitly_typed_lambda_expression](ide0350.md#csharp_style_prefer_implicitly_typed_lambda_expression) | +> | [IDE0360](ide0360.md) | Simplify property accessor | [csharp_style_prefer_simple_property_accessors](ide0360.md#csharp_style_prefer_simple_property_accessors) | +> | [IDE0370](ide0370.md) | Remove unnecessary suppression | | +> | [IDE0380](ide0380.md) | Remove unnecessary 'unsafe' modifier | | > | [IDE1005](ide1005.md) | Use conditional delegate call | [csharp_style_conditional_delegate_call](ide1005.md#csharp_style_conditional_delegate_call) | > | [IDE1006](naming-rules.md) | Naming styles | | > | [IDE2000](ide2000.md) | Avoid multiple blank lines | [dotnet_style_allow_multiple_blank_lines_experimental](ide2000.md#dotnet_style_allow_multiple_blank_lines_experimental)† | diff --git a/docs/fundamentals/code-analysis/style-rules/language-rules.md b/docs/fundamentals/code-analysis/style-rules/language-rules.md index bd86cd6744ebd..6ca1f966d419c 100644 --- a/docs/fundamentals/code-analysis/style-rules/language-rules.md +++ b/docs/fundamentals/code-analysis/style-rules/language-rules.md @@ -1,7 +1,7 @@ --- title: Code-style language and unnecessary code rules description: Learn about the different code-style rules for using C# and Visual Basic language constructs and for finding unnecessary code. -ms.date: 03/25/2025 +ms.date: 11/07/2025 helpviewer_keywords: - language code style rules [EditorConfig] - language rules @@ -172,6 +172,7 @@ C# style rules: - [Use collection expression for new (IDE0306)](ide0306.md) - [Use unbound generic type (IDE0340)](ide0340.md) - [Use implicitly typed lambda (IDE0350)](ide0350.md) +- [Simplify property accessor (IDE0360)](ide0360.md) Visual Basic style rules: @@ -205,6 +206,7 @@ C# style rules: - [Struct can be made 'readonly' (IDE0250)](ide0250.md) - [Member can be made 'readonly' (IDE0251)](ide0251.md) - [Make anonymous function static (IDE0320)](ide0320.md) +- [Remove unnecessary `unsafe` modifier (IDE0380)](ide0380.md) ### New-line preferences @@ -259,6 +261,10 @@ C# style rules: - [Remove unnecessary suppression (IDE0079)](ide0079.md) +C# style rules: + +- [Remove unnecessary suppression (null-forgiving operator) (IDE0370)](ide0370.md) + ### `This.` and `me.` preferences .NET style rules (C# and Visual Basic): diff --git a/docs/navigate/tools-diagnostics/toc.yml b/docs/navigate/tools-diagnostics/toc.yml index 3bfea72f9aa3b..ef7767c738afb 100644 --- a/docs/navigate/tools-diagnostics/toc.yml +++ b/docs/navigate/tools-diagnostics/toc.yml @@ -3874,6 +3874,12 @@ items: href: ../../fundamentals/code-analysis/style-rules/ide0340.md - name: IDE0350 href: ../../fundamentals/code-analysis/style-rules/ide0350.md + - name: IDE0360 + href: ../../fundamentals/code-analysis/style-rules/ide0360.md + - name: IDE0370 + href: ../../fundamentals/code-analysis/style-rules/ide0370.md + - name: IDE0380 + href: ../../fundamentals/code-analysis/style-rules/ide0380.md - name: IDE1005 href: ../../fundamentals/code-analysis/style-rules/ide1005.md - name: IDE2000 From 280f8d772af006991ce5f189671c2f71bb24f542 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 08:54:09 -0800 Subject: [PATCH 4/4] Add clarification that hosting APIs require framework-dependent deployments (#49595) --- docs/core/tutorials/netcore-hosting.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/core/tutorials/netcore-hosting.md b/docs/core/tutorials/netcore-hosting.md index 9c7272d6d6d0c..4b56b3d22bbd7 100644 --- a/docs/core/tutorials/netcore-hosting.md +++ b/docs/core/tutorials/netcore-hosting.md @@ -24,6 +24,9 @@ You also need to build a .NET component to test the host with, so you should ins Hosting the .NET runtime is done with the `nethost` and `hostfxr` libraries' APIs. These entry points handle the complexity of finding and setting up the runtime for initialization and allow both launching a managed application and calling into a static managed method. +> [!IMPORTANT] +> The `nethost` and `hostfxr` hosting APIs only support framework-dependent deployments. Self-contained deployments should be treated as stand-alone executables. If you're evaluating deployment models for your application, use a framework-dependent deployment to ensure compatibility with these native hosting APIs. + ## Create a host using `nethost.h` and `hostfxr.h` A [sample host](https://github.com/dotnet/samples/tree/main/core/hosting) demonstrating the steps outlined in the tutorial below is available in the dotnet/samples GitHub repository. Comments in the sample clearly associate the numbered steps from this tutorial with where they're performed in the sample. For download instructions, see [Samples and Tutorials](../../samples-and-tutorials/index.md#view-and-download-samples).