Skip to content

Commit

Permalink
Merge pull request #317 from terrajobst/net-standard-recommendation
Browse files Browse the repository at this point in the history
Add design document for issuing a warning when targeting netstandard1.x
  • Loading branch information
terrajobst authored Jun 1, 2024
2 parents 6d8b13c + 83157fd commit 7e18508
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 0 deletions.
1 change: 1 addition & 0 deletions INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Use update-index to regenerate it:
| 2023 | [Experimental APIs](accepted/2023/preview-apis/preview-apis.md) | [Immo Landwerth](https://github.com/terrjobst) |
| 2023 | [Multi-threading on a browser](accepted/2023/wasm-browser-threads.md) | [Pavel Savara](https://github.com/pavelsavara) |
| 2023 | [net8.0-browser TFM for applications running in the browser](accepted/2023/net8.0-browser-tfm.md) | [Javier Calvarro](https://github.com/javiercn) |
| 2024 | [.NET Standard Targeting Recommendations](accepted/2024/net-standard-recommendation.md) | [Immo Landwerth](https://github.com/terrajobst), [Viktor Hofer](https://github.com/ViktorHofer) |

## Drafts

Expand Down
173 changes: 173 additions & 0 deletions accepted/2024/net-standard-recommendation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# .NET Standard Targeting Recommendations

**Owner** [Immo Landwerth](https://github.com/terrajobst) | [Viktor Hofer](https://github.com/ViktorHofer)

We have already said that there is [no new version of .NET
Standard][net-standard-future] and that the replacement moving forward is to
just target the platform-neutral `netX.Y` [base framework][tfm] (with `x.y >=
5.0`) of .NET Core.

For customers that need to author code that still needs to be consumed by .NET
Framework, the recommendation is to continue using `netstandard2.0`. There is
very little reason to target .NET Standard 2.1 because you lose .NET Framework
while only gaining very little few additional APIs. And if you don't care about
.NET Framework support, then just target .NET Core directly; at least then you
get access to a lot more functionality, in exchange for the reduced reach.

There is basically no reason to target .NET Standard 1.x any more as all .NET
implementations that are still supported, can reference .NET Standard 2.0
libraries.

However, we have found that many customers still target .NET Standard 1.x. We
found out the reasons boil down to one of two things:

1. Targeting the lowest possible versions is considered better
2. It was already like that and there is no reason to change

The first argument has merit in a world where .NET Standard continues to produce
new versions. Since that's no longer the case you might as well update to a
later version that allows you to use more functionality. We found the biggest
jump in productivity is with .NET Standard 2.0 because it also supports
[referencing .NET Framework libraries][netfx-compate-mode], which is useful in
cases where you modernize existing applications and have some mixture until you
can upgrade all the projects.

The second reason is always valid; however, in cases when you're actively
maintaining a code base it makes sense to upgrade to avoid missing out on
features that could have made your life easier and you didn't realize exist
because code completion simply didn't advertise them.

## Scenarios and User Experience

### Building a project targeting .NET Standard

Jackie is assigned a work item to add a feature that requires writing code in
the shared business logic project. That project happens to target .NET Standard
1.4. She doesn't know why because the project was built before her time on the
team. The first time she compiles in Visual Studio she sees a warning:

> warning NETSDK1234: Contoso.BusinessLogic.csproj: Targeting .NET Standard
> prior to 2.0 is no longer recommended. See \<URL\> for more details.
Following the link, she finds a page that inform her that all supported .NET
implementations allow using .NET Standard 2.0 or higher. She asks one of her
colleagues and she remembers that they used .NET Standard 1.4 because at some
point her team also maintained a Windows Phone app (which, to everybody's
disappointment no longer exists).

Jackie decides to upgrade the project to .NET Standard 2.0. She later realizes
that this was a good idea because it enables her to use many of the
`Microsoft.Extensions` libraries that make her life a lot easier, specifically
configuration and DI.

## Requirements

### Goals

* Issue a warning when *building* a project targeting `netstandard1.x` with the
.NET 9 SDK

### Non-Goals

* Issue a warning when building a project targeting `netstandard2.x`
* Issue a warning when consuming a library that was built for .NET Standard 1.x.
* Issue a warning building with a .NET SDK prior to 9.0

## Stakeholders and Reviewers

* Libraries team
* SDK team
* Build team
* NuGet team

## Design

The .NET SDK will check the `TargetFramework` property. If it uses
`netstandardX.Y` with `X.Y < 2.0` it will produce the following warning:

> Targeting .NET Standard prior to 2.0 is no longer recommended. See \<URL\> for
> more details.
* The warning should have a diagnostic ID (prefixed `NETSDK` followed by a four
digit number).
* The warning should be suppressable via the `NoWarn` property.
* The URL should be point to the documented ID [here][sdk-errors] (not sure why
it says `sdk-errors` -- I don't believe we have a section for warnings).

## Q & A

## What is the downside of targeting .NET Standard 1.x?

There is a major difference in how tooling works for .NET Standard 1.x vs 2.x:

* .NET Standard 1.x was based on packages, that is, if you target .NET Standard
1.x you end up referencing about ~70-100 packages (depending on whether you
also target a specific runtime identifier). Those are also persisted in the
resulting NuGet package which causes consumers having to restore them as well.

* .NET Standard 2.x doesn't use packages; the resulting NuGet package doesn't
depend on any packages, just like targeting specific frameworks generally
doesn't.

In principle we could change the way tooling works for .NET Standard 1.x but we
don't really see the value for two reasons:

1. The additional platforms that .NET Standard 1.x reaches are mostly out of
support.

2. [.NET Standard itself is no longer updated][net-standard-future]. We believe
the new OS-specific frameworks starting with .NET 5 are a much easier and
better model therefore supersede .NET Standard.

If you target .NET Standard 1.x you're limiting yourself to a subset of .NET
Framework 4.5, which shipped about 12 years ago. A lot of innovation has
happened since then that you're missing out on. If you need to support older
frameworks that Microsoft doesn't support, this might be an intentional choice
in which case suppressing the warning makes total sense.

However, we believe the vast majority of people don't have such a requirement
and would be better off targeting .NET Standard 2.0 or .NET 5+ instead.

## Should I drop .NET Standard altogether?

If you need to produce a NuGet package that works on .NET Framework as well as
modern .NET flavors then using .NET Standard 2.0 is still the best solution for
you -- and your consumers.

If you drop .NET Standard and instead just multi-target for .NET Framework and
.NET 5+, you force your consumers to do the same, which is generally not
necessary and thus very much undesirable.

However, if you don't have to support .NET Framework then you're likely better
off just targeting .NET 5+.

### Didn't you promise that .NET Standard is supported forever?

We promised that future .NET implementations will continue to support
*consuming* libraries built for .NET Standard, all the way back to 1.0. That is
different from promising that we'll support *producing* .NET Standard binaries
forever; that would only make sense if .NET Standard is still the best way to
build reusable libraries. And [since .NET 5 and the platform-specific
flavors][tfm] of .NET we think there is now a better way to do so.

The original promise around consumption still stands: existing libraries built
for .NET Standard 1.0 can still be consumed and we have no plans on changing
that. So any existing investment in building a library that can be consumed in
as many places as possible still carries forward.

### Can I continue to build libraries targeting .NET Standard 1.x?

Yes. There *may* come a time where the .NET SDK stops supporting building .NET
Standard libraries, but we currently have no plans on doing so as the targeting
packs for .NET Standard 1.x aren't bundled with the SDK and are only downloaded
on demand already; thus, the benefit to removing the support for building .NET
Standard 1.x seems marginal.

We believe our ecosystem is better off targeting at least .NET Standard 2.0
which is why we want to issue a warning, but the motivation isn't in us being
able to remove the support for building.

[net-standard-future]: https://devblogs.microsoft.com/dotnet/the-future-of-net-standard/
[tfm]: https://github.com/dotnet/designs/blob/main/accepted/2020/net5/net5.md
[netfx-compate-mode]: https://learn.microsoft.com/en-us/dotnet/core/porting/#net-framework-compatibility-mode
[sdk-errors]: https://learn.microsoft.com/en-us/dotnet/core/tools/sdk-errors/

0 comments on commit 7e18508

Please sign in to comment.