Drop support for net452?
Other similar projects have started to drop it and given that MS support ended 2016 we can also consider dropping it.
What would be the highest new full framework we can lock on?
Or can we go netstandard2.0 only?
4.6 seems to be the oldest supported version by Windows 10. Unless there is some very useful functionality in 4.7, it would probably be the most reasonable to target 4.6.2. I'm rather wondering, whether we should just start targeting .NET Standard 2 only and drop the framework specific parts?
That would definitely make things easier and speed up the build times etc so that would be an interesting direction.
What use impact would that have?
A quick look show that we would mostly lose support for the old configuration stuff

but we would have to do some more thorough research
4.6 seems to be the oldest supported version by Windows 10. Unless there is some very useful functionality in 4.7, it would probably be the most reasonable to target 4.6.2. I'm rather wondering, whether we should just start targeting .NET Standard 2 only and drop the framework specific parts?
Just a word of caution, Microsoft states that even though 4.6.x can reference .Net standard 2.0 that it has incompatibilities and they recommend using 4.7. I wish the explanation on the link below went into the details of that statement.
https://docs.microsoft.com/en-us/dotnet/standard/net-standard
This is an area I've thought about a lot, I definitely think we should bump the .NET Framework version, though I'm not sure it being not supported is the proper justification for that.
As mentioned in the article @andreasohlund linked to, the .NET Framework doesn't have its own support lifecycle. Its support is tied to the support of the versions of Windows it shipped with. That means that net452 is still in some level of support, because Windows Server 2012 is still in extended support, and net452 is still supported as the oldest 4.x release on that OS.
However, if we were strictly tied to keeping support for the oldest .NET Framework version, then we'd still be supporting net35 because that is also still supported on every version of Windows currently shipping. It's only as of Windows 10 1809 that Microsoft has unbundled it from the Windows support lifecycle, so it's still got another decade before it's finally gone.
So if we are okay with some versions of Windows needing a .NET Framework installation before being able to run NServiceBus, which version should we move up to?
I propose we support net472+ and .NET Core 2.x+ though the following target frameworks: netstandard2.0;netcoreapp3.1
Let me break that down and explain why I'm proposing this.
netstandard2.0
This would be the assembly that gets used when when running on .NET Framework.This in theory would get us support for net461 and up, but as @cfranchuk has mentioned, there's a problem with this. While net461 - net471 claim to support netstandard2.0, they really don't. They need a bunch of extra shim assemblies, which end up causing all sorts of problems. Realistically, net472 and net48 are the only versions that actually support it.
Unfortunately, there's no built-in way to prevent net461 - net471 from trying to use the netstandard2.0 assembly, so we should include an MSBuild target to prevent it from being used on anything before net472.
The netstandard2.0 assembly would also be used when running .NET Core 2.1 (and 2.2 but that goes out of support on December 23rd).
netcoreapp3.1
This would be the assembly that would get used when running .NET Core 3.1. There's no point supporting 3.0 since 3.1 comes out ~~this month~~ today and 3.0 will then be going out of support in March. This would also let us take advantage of any 3.1-specific APIs that we'd like to.
Why not netstandard2.1?
While there is an updated .NET Standard revision, I don't really see it gaining us anything by using it. We don't support running on anything but .NET Core anyway, so it's we aren't losing any other platforms. We also need to use some APIs that aren't part of .NET Standard, which is why we ended up with several package dependencies in NSB 7.x. Most (all?) of the dependencies would go away if we target netcoreapp3.1 instead.
What about future releases?
.NET Core does have configurable version roll-forward capability. By default, it will roll forward to a newer minor release. So if we target netcoreapp3.1 and the machine only has 3.2 installed, it will continue to work. .NET Core 3.x can also be configured for major version roll forward, so in theory when .NET 5 comes out next year, it might be possible for someone to try and make it work.
This also puts us in a potentially desirable position of needing to explicitly add support for the next major version by adding a TFM, instead of what we have right now where the netstandard2.0 assembly will automatically work with .NET Core 3.x without us having validated compatibility.
Overall I think this strikes the right balance of letting us continue to support the past while aiming us in the right direction for the future.
A quick look show that we would mostly lose support for the old configuration stuff
but we would have to do some more thorough research
I believe we've positioned all of that with obsolete warnings to indicate it was all going away in the next major anyway.
This is an area I've thought about a lot, I definitely think we should bump the .NET Framework version, though I'm not sure it being not supported is the proper justification for that.
As mentioned in the article @andreasohlund linked to, the .NET Framework doesn't have its own support lifecycle. Its support is tied to the support of the versions of Windows it shipped with. That means that
net452is still in some level of support, because Windows Server 2012 is still in extended support, andnet452is still supported as the oldest 4.x release on that OS.However, if we were strictly tied to keeping support for the oldest .NET Framework version, then we'd still be supporting
net35because that is also still supported on every version of Windows currently shipping. It's only as of Windows 10 1809 that Microsoft has unbundled it from the Windows support lifecycle, so it's still got another decade before it's finally gone.So if we are okay with some versions of Windows needing a .NET Framework installation before being able to run NServiceBus, which version should we move up to?
I propose we support
net472+ and .NET Core 2.x+ though the following target frameworks:netstandard2.0;netcoreapp3.1Let me break that down and explain why I'm proposing this.
netstandard2.0This would be the assembly that gets used when when running on .NET Framework.This in theory would get us support for
net461and up, but as @cfranchuk has mentioned, there's a problem with this. Whilenet461-net471claim to supportnetstandard2.0, they really don't. They need a bunch of extra shim assemblies, which end up causing all sorts of problems. Realistically,net472andnet48are the only versions that actually support it.Unfortunately, there's no built-in way to prevent
net461-net471from trying to use thenetstandard2.0assembly, so we should include an MSBuild target to prevent it from being used on anything beforenet472.The
netstandard2.0assembly would also be used when running .NET Core 2.1 (and 2.2 but that goes out of support on December 23rd).
netcoreapp3.1This would be the assembly that would get used when running .NET Core 3.1. There's no point supporting 3.0 since 3.1 comes out this month and 3.0 will then be going out of support in January. This would also let us take advantage of any 3,1-specific APIs that we'd like to.
Why not
netstandard2.1?While there is an updated .NET Standard revision, I don't really see it gaining us anything by using it. We don't support running on anything but .NET Core anyway, so it's we aren't losing any other platforms. We also need to use some APIs that aren't part of .NET Standard, which is why we ended up with several package dependencies in NSB 7.x. Most (all?) of the dependencies would go away if we target
netcoreapp3.1instead.What about future releases?
.NET Core does have configurable version roll-forward capability. By default, it will roll forward to a newer minor release. So if we target
netcoreapp3.1and the machine only has 3.2 installed, it will continue to work. .NET Core 3.x can also be configured for major version roll forward, so in theory when .NET 5 comes out next year, it might be possible for someone to try and make it work.This also puts us in a potentially desirable position of needing to explicitly add support for the next major version by adding a TFM, instead of what we have right now where the
netstandard2.0assembly will automatically work with .NET Core 3.x without us having validated compatibility.Overall I think this strikes the right balance of letting us continue to support the past while aiming us in the right direction for the future.
That is a really thorough analysis @bording. As a general rule of thumb when writing a library that targets .net standard I try to reference the minimum version required. When creating a project that targets a runtime (full or .net core) I strive for the latest version. Of course when making these decisions you have to weigh the baggage of backwards compatibility. Having too much backwards compatibility can lead to stagnation and/or bloat. Your statement and reasoning for targeting .net standard 2.0 versus 2.1 seems sound.
Just noting that dropping net452 would allow us to update to latest Fody and PublicAPIGenerator
This was done in v8, closing