-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #317 from terrajobst/net-standard-recommendation
Add design document for issuing a warning when targeting netstandard1.x
- Loading branch information
Showing
2 changed files
with
174 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/ |