diff --git a/accepted/2024/net10.md b/accepted/2024/net10.md index 5e08695e5..7cfcf3e19 100644 --- a/accepted/2024/net10.md +++ b/accepted/2024/net10.md @@ -37,54 +37,142 @@ This document proposes how to address this. ## Design -Considering that .NET Framework 1.0 is out of support for a while and Visual -Studio doesn't even support building for anything older than .NET Framework 2.0, -it seems very doable to make `net10` mean .NET 10. The question is what happens -with all the other frameworks, such as `net20`, `net452` etc. Quite a few of -those are still supported and actively used. +We want to steer people towards a proper version syntax, that is + +```xml +netX.Y.Z +``` -Here is the proposal: +Examples include `net9.0`, `net10.0`, `net4.5.1`. This syntax makes it +unambiguous. -* Make `net10` mean .NET 10 and `net11` mean .NET 11 but keep all higher - versions as-is (`net20` still means .NET Framework 2.0). -* The .NET SDK produces a warning if the `` property doesn't - contain a period. +Proposal: -This results in two things: +* Fail the build if the TFM is `net10` or `net11` with an error message + > This framework syntax is unsupported because it's unambiguous. If you mean + > .NET Framework 1.0, use `net1.0`. If you mean .NET 10, use `net10.0`. +* If the TFM is neither `net10` nor `net11`, produce a warning if it doesn't + contain a period: + > This framework syntax is obsolete. You should use periods to separate + > version components. -1. Existing behaviors won't change -2. People making the mistake today don't get unintelligible errors which makes - the warning more visible +The reason to fail the build is because in practice someone trying to target +.NET 10 will most likely fail anyway because the either don't have the .NET +Framework 3.5 targeting pack -- or worse -- they do, but the code doesn't +compile because it's meant for modern .NET Core, not a 25 year old .NET +Framework 1.0. By failing it early it turns an actionable error into something +that makes more sense to the user. -The next version where this is a problem is .NET 20, which will ship in 2035 -(assuming we keep the schedule). I think 10 years of warning people to include a -period ought to be enough to avoid this problem. In fact, we should consider -making omitting a version number a build break in, say, .NET 12. +The reason to issue the warning is to avoid any ambiguities moving forward. + +> [!NOTE] +> +> Please note that this change only applies to the .NET Core SDK, i.e. SDK-style +> projects. Old school .NET Framework CSPROJ files will be unaffected by this +> change because the representation of the target framework is already a proper +> version string. ### Usage -| GitHub Usage of a Framework | Without `.0` | With `.0` | Percent | -| --------------------------------------- | -----------: | --------: | ------- | -| [`net5`] vs [`net5.0`] | 916 | 142k | 0.6% | -| [`net6`] vs [`net6.0`] | 2.3k | 436k | 0.5% | -| [`net7`] vs [`net7.0`] | 520 | 138k | 0.4% | -| [`net8`] vs [`net8.0`] | 704 | 381k | 0.2% | -| [`net9`] vs [`net9.0`] | 9 | 4.3k | 0.2% | -| [`netstandard2`] vs [`netstandard2.0`] | 83 | 132k | 0.1% | +Below is a comparison how much a given TFM syntax is being used on GitHub. As +you can see, for modern TFMs syntax wit an explicit period is most widely used. + +| GitHub Usage of a TFM syntax | `netX` | `netXY` | `netX.Y` | +| ----------------------------------------------------- | -----: | ------- | -------: | +| [`net5`] [`net50`] [`net5.0`] | 916 | 181 | 142k | +| [`net6`] [`net60`] [`net6.0`] | 2.3k | 273 | 436k | +| [`net7`] [`net70`] [`net7.0`] | 520 | 104 | 138k | +| [`net8`] [`net80`] [`net8.0`] | 704 | 46 | 381k | +| [`net9`] [`net90`] [`net9.0`] | 9 | 1 | 4.3k | +| [`netstandard2`] [`netstandard20`] [`netstandard2.0`] | 83 | 148 | 132k | [`net5`]: https://github.com/search?q=net5%3C%2FTargetFramework%3E+lang%3Axml&type=code [`net6`]: https://github.com/search?q=net6%3C%2FTargetFramework%3E+lang%3Axml&type=code [`net7`]: https://github.com/search?q=net7%3C%2FTargetFramework%3E+lang%3Axml&type=code [`net8`]: https://github.com/search?q=net8%3C%2FTargetFramework%3E+lang%3Axml&type=code [`net9`]: https://github.com/search?q=net9%3C%2FTargetFramework%3E+lang%3Axml&type=code + +[`net50`]: https://github.com/search?q=net50%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net60`]: https://github.com/search?q=net60%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net70`]: https://github.com/search?q=net70%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net80`]: https://github.com/search?q=net80%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net90`]: https://github.com/search?q=net90%3C%2FTargetFramework%3E+lang%3Axml&type=code + [`net5.0`]: https://github.com/search?q=net5.0%3C%2FTargetFramework%3E+lang%3Axml&type=code [`net6.0`]: https://github.com/search?q=net6.0%3C%2FTargetFramework%3E+lang%3Axml&type=code [`net7.0`]: https://github.com/search?q=net7.0%3C%2FTargetFramework%3E+lang%3Axml&type=code [`net8.0`]: https://github.com/search?q=net8.0%3C%2FTargetFramework%3E+lang%3Axml&type=code [`net9.0`]: https://github.com/search?q=net9.0%3C%2FTargetFramework%3E+lang%3Axml&type=code + [`netstandard2`]: https://github.com/search?q=netstandard2%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`netstandard20`]: https://github.com/search?q=netstandard20%3C%2FTargetFramework%3E+lang%3Axml&type=code [`netstandard2.0`]: https://github.com/search?q=netstandard2.0%3C%2FTargetFramework%3E+lang%3Axml&type=code +For .NET Framework frameworks the most dominant syntax is used is without +periods, which is to be expected given that was the encouraged syntax: + +| GitHub Usage of a TFM syntax | `netX` | `netXY` | `netX.Y` | +| ----------------------------- | -----: | ------: | -------: | +| [`net1`] [`net10`] [`net1.0`] | 0 | 75 | 0 | +| [`net11`] [`net1.1`] | | 1 | 0 | +| [`net2`] [`net20`] [`net2.0`] | 1 | 15k | 6 | +| [`net3`] [`net30`] [`net3.0`] | 0 | 0 | 3 | +| [`net35`] [`net3.5`] | | 42k | 16 | +| [`net4`] [`net40`] [`net4.0`] | 0 | 24k | 26 | +| [`net45`] [`net4.5`] | | 13k | 48 | +| [`net451`] [`net4.5.1`] | | 988 | 3 | +| [`net452`] [`net4.5.2`] | | 35k | 107 | +| [`net46`] [`net4.6`] | | 39k | 17 | +| [`net461`] [`net4.6.1`] | | 84k | 43 | +| [`net462`] [`net4.6.2`] | | 82k | 34 | +| [`net47`] [`net4.7`] | | 13k | 25 | +| [`net471`] [`net4.7.1`] | | 19k | 23 | +| [`net472`] [`net4.7.2`] | | 159k | 146 | +| [`net48`] [`net4.8`] | | 134k | 320 | +| [`net481`] [`net4.8.1`] | | 652 | 37 | + +[`net1`]: https://github.com/search?q=net1%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net2`]: https://github.com/search?q=net2%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net3`]: https://github.com/search?q=net3%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4`]: https://github.com/search?q=net3%3C%2FTargetFramework%3E+lang%3Axml&type=code + +[`net10`]: https://github.com/search?q=net10%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net11`]: https://github.com/search?q=net11%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net20`]: https://github.com/search?q=net20%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net30`]: https://github.com/search?q=net3%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net35`]: https://github.com/search?q=net35%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net40`]: https://github.com/search?q=net40%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net45`]: https://github.com/search?q=net45%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net451`]: https://github.com/search?q=net451%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net452`]: https://github.com/search?q=net452%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net46`]: https://github.com/search?q=net46%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.6`]: https://github.com/search?q=net4.6%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net461`]: https://github.com/search?q=net461%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net462`]: https://github.com/search?q=net462%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net47`]: https://github.com/search?q=net47%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net471`]: https://github.com/search?q=net471%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net472`]: https://github.com/search?q=net472%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net48`]: https://github.com/search?q=net48%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net481`]: https://github.com/search?q=net481%3C%2FTargetFramework%3E+lang%3Axml&type=code + +[`net1.0`]: https://github.com/search?q=net1.0%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net1.1`]: https://github.com/search?q=net1.1%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net2.0`]: https://github.com/search?q=net2.0%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net3.0`]: https://github.com/search?q=net3.0%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net3.5`]: https://github.com/search?q=net3.5%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.0`]: https://github.com/search?q=net4.0%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.5`]: https://github.com/search?q=net4.5%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.5.1`]: https://github.com/search?q=net4.5.1%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.5.2`]: https://github.com/search?q=net4.5.2%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.6.1`]: https://github.com/search?q=net4.6.1%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.6.2`]: https://github.com/search?q=net4.6.2%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.7`]: https://github.com/search?q=net4.7%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.7.1`]: https://github.com/search?q=net4.7.1%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.7.2`]: https://github.com/search?q=net4.7.2%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.8`]: https://github.com/search?q=net4.8%3C%2FTargetFramework%3E+lang%3Axml&type=code +[`net4.8.1`]: https://github.com/search?q=net4.8.1%3C%2FTargetFramework%3E+lang%3Axml&type=code + + ## Q & A ### What about `net10.0` @@ -97,3 +185,17 @@ when using `net10` will most likely fail because the SDK doesn't support targeting it, which will drown out the warning telling you to use period. Failing it only for `net10` would be possible but feel odd because we'd prefer periods for all framework names, not just for `net10.0`. + +# Why don't we make `net10` just work work? + +Considering that .NET Framework 1.0 is out of support for a while and Visual +Studio doesn't even support building for anything older than .NET Framework 2.0, +it seems very doable to make `net10` mean .NET 10. + +There are two downsides to this: + +1. It makes a syntax work that we don't want to promote +2. The other (widely used) monikers `net20`, `net452`, `net48`, need to continue + to work and mean what they mean today, which is confusing. +3. It requires changing parsing rules in the NuGet library, which might have + unforeseen ripple effects.