Skip to content
This repository has been archived by the owner on Sep 13, 2022. It is now read-only.

Support .Net Framework (4.8?) for netstandard 2.1 #859

Closed
Daniel-Svensson opened this issue Aug 28, 2018 · 58 comments
Closed

Support .Net Framework (4.8?) for netstandard 2.1 #859

Daniel-Svensson opened this issue Aug 28, 2018 · 58 comments
Assignees

Comments

@Daniel-Svensson
Copy link

There is currently no mention here about which platforms will be supported apart from .net core. So adding this issue to track the framework support.

Netstandard is a good way to target all the major .net platforms. As such it should continue to support the .Net Framework which is still very much used.

@terrajobst
Copy link
Member

The .NET Framework 4.8 feature set is still being decided on, which is why we haven't shared any plans yet. As soon as that's decided, I'll update the planning doc.

@terrajobst terrajobst added this to the .NET Standard 2.1 milestone Oct 17, 2018
@terrajobst terrajobst self-assigned this Oct 31, 2018
@springy76
Copy link

springy76 commented Nov 2, 2018

I just wanted to ask the same question.

Now that 3 days ago it has been announced that asp.net.core will not support .netframework anymore: https://blogs.msdn.microsoft.com/webdev/2018/10/29/a-first-look-at-changes-coming-in-asp-net-core-3-0/

This sounds like netstandard2.1 for netframework will not happen at all.

But this rises another question: If everyone has to reference netcore soon, is there any sense for netstandard at all?

@johnduhart
Copy link

Latest blog post makes this clear, netfx 4.8 will not support .NET Standard 2.1.

https://blogs.msdn.microsoft.com/dotnet/2018/11/05/announcing-net-standard-2-1/

@terrajobst
Copy link
Member

Yep. Closing.

@springy76
Copy link

springy76 commented Nov 6, 2018

RIP .NET Framework.

It will not take long till the first NuGet dependency will become netstandard2.1+ only, and then BOOM!

@slang25
Copy link

slang25 commented Nov 6, 2018

People will be mutlitargeting netstandard2.0 for a long time. It's not reasonable to expect all frameworks to be locked together in features.

@trampster
Copy link

netstandard was proposed as a solution to nightmare that was PCL. It was to be a common set of features that all frameworks would support. This just killed that.

Either we consider .NET Framework to be dead and therefore not included in all frameworks. or netstandard has failed in it's goals.

@slang25
Copy link

slang25 commented Nov 7, 2018

No, it was never a goal to have all runtimes support the same features. It was to simplify how we refer to API sets so that we could have broader terms for them. All target frameworks support .NET Standard as a concept, and implement some level/version of netstandard, but they don't all support the latest version of netstandard, that is a deliberate fundamental part of how it works.

@trampster
Copy link

That's a shame because with .NET Standard 2.0 we had the ability to target everything with the one library. However with new Features like span restricted to 2.1, library devs are back to having to make compromises to ether multi target and emit features from some frameworks, or not use new features at all.

@springy76
Copy link

People will be mutlitargeting netstandard2.0 for a long time

Time will show but I don't believe. Nobody voluntarily floods his code with #if pragmas when not being forced to. Similarily when I write code using C#7.3 features I don't spend time in doubling my code by trying to find out how to write the same using C#7.0.

@slang25
Copy link

slang25 commented Nov 8, 2018

That comparison doesn't work for a number of reasons.

But I do hear what you are saying, if someone creates a new library, they might select netstandard2.1 and they will be excluding the full framework from consuming it. I'm hoping that the defaults and the guidance makes it clear the consequences when you are doing "File -> New...". I don't see libraries with existing users just dropping netstandard2.0, there will be a period of conditional compilation, and that would likely be kept for years. We will see.

@NetMage
Copy link

NetMage commented Nov 29, 2018

And now a lot of C# 8 requires .Net Standard 2.0 / .Net Core 3.0 and won't be working with .Net 4.8.

@gautelo
Copy link

gautelo commented Feb 6, 2019

Does that mean that there will be a .Net Framework 4.8.x or 4.9.x that will support netstandard 2.1? I mean, if there is no plan to implement the standard in anything but dotnet core, then why not simply work on dotnet core?

Don't get me wrong, I think that would be a mistake, but only under my assumption that the full framework would continue to support new netstandard versions.

If there are no such plans, I'm basically receiving a message saying I should not write libraries targetting netstandard 2.1. Is that what you want? I know I'd like to see my code thrive and be used.

If you're trying to send a different message, you need to clarify!

Or is the reasoning here that I should only target 2.1 alongside other targets and code conditionally for each one? If so, that's an abysmal message. I do not want to do that. It sounds like a mess and a ton of pain... I suppose such branching is fine for large public facing libraries. But for internal libraries, I should not have to do that.

I realise that there are several teams trying to coordinate these things, and that getting everyone on the same page can be hard. But this needs to be sorted out...

@danmoseley
Copy link
Member

no plan to implement the standard in anything but dotnet core, then why not simply work on dotnet core?

We expect Mono/Xamarin to support it, and most likely Unity to in due course.

@gautelo
Copy link

gautelo commented Feb 11, 2019

@danmosemsft I see. My mistake. I've been thinking in terms of only two of the platforms; fullframework & dotnet core.

At least then it makes sense, even if I think it's a pity that the fullframework won't get support. I suppose that simply means we should all hasten to move away from fullframework asap, or be left in the dust. ;)

@danmoseley
Copy link
Member

@gautelo :)

@springy76
Copy link

If you look at my comment from Nov 2th, we already have entered a loop here ;)

@gautelo
Copy link

gautelo commented Feb 12, 2019

@springy76 Yeah, I read the whole thing. I just wanted to voice my support and add some pressure.

@lostmsu
Copy link

lostmsu commented Mar 4, 2019

I am specifically concerned about System.Range and System.Index, that are part of C# 8.
Unless they are supported, my scientific library will have to drop them as a feature to be usable in enterprise.

@JensNordenbro
Copy link

JensNordenbro commented Mar 8, 2019

I worry this will hamper libraries that want to use the high performance constructs of .netstandard2.1 and hence be counter productive since .NET Core applications also will run without the Span, SIMD, Whatever features inside the libraries when .NET Standard 2.0 is the common ground.

@behoyh
Copy link

behoyh commented Mar 25, 2019

This puts our developers in between a rock and a hard place, since there are libraries that we use to access our core database that I worry will never be updated to target .NET Standard. So the choice we will have to make is either go full .NET Framework or stay on .NET Core 2.1, both of which are painful decisions to make.

@jzabroski
Copy link

@behoyh I guess the bright side is there is no shortage of development jobs to move piles of code around and put those .NET Framework piles of code into .NET Core 3 piles of code.

May want to buy two things this summer: Stock in Caterpillar, and a JetBrains ReSharper license.

@jzabroski
Copy link

That's a shame because with .NET Standard 2.0 we had the ability to target everything with the one library. However with new Features like span restricted to 2.1, library devs are back to having to make compromises to ether multi target and emit features from some frameworks, or not use new features at all.

In short: Superpackages that span multiple themes are a bad idea.

Unfortunately, it's less clear if smaller superpackages + ThemePacks are better or even worse. (ThemePacks are my own moniker for describing the idea that perhaps we should have netstandard-system, netstandard-gui, netstandard-data, netstandard-web, etc.)

@albertwoo
Copy link

I am using asp.net core 2.2 and target to net471 because of legacy libraries (a lot of them which is out my control). And now I cannot upgrade to asp.net core 3,and efcore 3 which is sad. Maybe .net 5 can support legacy libraries.? If not then I have to stay in asp.net core 2.2 forever?

@springy76
Copy link

@albertwoo (asp)netcore 3 can reference and use net4x assemblies or NuGet packages. You will get compile time warnings and maybe MethodNotFound exceptions on run-time. But it in most cases I've seen so far, it just works because netcore3 has added a lot of APIs from net4x.

@terrajobst
Copy link
Member

I am using asp.net core 2.2 and target to net471 because of legacy libraries (a lot of them which is out my control). And now I cannot upgrade to asp.net core 3,and efcore 3 which is sad. Maybe .net 5 can support legacy libraries.? If not then I have to stay in asp.net core 2.2 forever?

Since .NET Standard 2.0 and .NET Core 2.0 you can reference .NET Framework libraries/NuGet packages. You'll get a warning when building, but we'll try to load the libraries. However, this will only work when the APIs used by the package exists. However, since then we've added a lot of libraries that provide more API support (e.g. the Windows Compatibility Pack). And with .NET Core 3.0, this also includes WinForms & WPF.

Post .NET Core 3, the set of supported .NET Framework will not grow in significant ways any more. See dotnet/announcements#130 for details.

@danmoseley
Copy link
Member

As well as the posting @terrajobst linked above, this blog post is relevant:
https://devblogs.microsoft.com/dotnet/net-core-is-the-future-of-net/

in particular

We will continue to both service and support .NET Framework, which includes bug–, reliability– and security fixes. It will continue to ship with Windows (much of Windows depends on .NET Framework) and we will continue to improve the tooling support for .NET in Visual Studio (Visual Studio is written on .NET Framework).
New applications should be built on .NET Core. .NET Core is where future investments in .NET will happen. Existing applications are safe to remain on .NET Framework which will be supported. Existing applications that want to take advantage of the new features in .NET should consider moving to .NET Core

@AndyDentFree
Copy link

You can use Xamarin Forms to do desktop with the WPF Backend targeting .NetCore 3.0 and with macOS but Linux desktop is still left hanging because GTK# targets .NetFramework

@springy76
Copy link

Just for common info: netstandard already has been declared "deprecated":
https://devblogs.microsoft.com/dotnet/the-future-of-net-standard/#problems-with-net-standard

@terrajobst
Copy link
Member

Just for common info: netstandard already has been declared "deprecated":
https://devblogs.microsoft.com/dotnet/the-future-of-net-standard/#problems-with-net-standard

That's not quite accurate. .NET Standard hasn't been deprecated; it has been merged with .NET Core into .NET 5. Therefore, all investments into .NET Standard carry forward to .NET 5 and all future versions. If a library is targeting .NET Standard today, there is no reason to move .NET 5 unless you need APIs that are net-new in .NET 5. So it's exactly the same as choosing between different versions of .NET Standard.

@jzabroski
Copy link

jzabroski commented Sep 28, 2020

That's not quite accurate. .NET Standard hasn't been deprecated; it has been merged with .NET Core into .NET 5. Therefore, all investments into .NET Standard carry forward to .NET 5 and all future versions. If a library is targeting .NET Standard today, there is no reason to move .NET 5 unless you need APIs that are net-new in .NET 5. So it's exactly the same as choosing between different versions of .NET Standard.

Is it, though? Say I packaged a .netstandard nuget package 3 years ago. What transitive assembly gets referenced in that package when I target .NET 5? My point is, I think there is a hidden time dimension (sequential coupling) that makes your statement either true or false. I predict this is where most people will have a lot of confusion, because there is no way to have assemblies as private dependencies other than to have a new AssemblyLoadContext.

I reserve the right to change my mind.

@terrajobst
Copy link
Member

terrajobst commented Sep 28, 2020

Not sure what you mean. A NuGet package with a .NET Standard binary built three years ago should install and run in a .NET 5 application just fine. If that doesn't work, I'd consider this a bug.

@jzabroski
Copy link

I'm referring to "private" dependencies that would need to roll forward on major version to get located for loading. (I edited my original response.)

@terrajobst
Copy link
Member

Could you provide an example? I'm still not sure I follow. The API surface of .NET Standard is entirely accumulative and we'll keep it this way for .NET 5. Thus, there shouldn't be a reason why something built three years no longer works because an API breaking change was performed.

@jzabroski
Copy link

If I have a project that targets netstandard2.0 and I "privately" (transitively) reference an OOB System package that references netstandard2.0, and then the consumer wants to reference that project in a .NET 5 app and have a "public" (top-level) dependency on the .NET 5 OOB reference, it's a bit hard for the consumer to understand why they get a DLL not found exception when the runtime loads the old dll and goes looking for the new dll, yes?

@terrajobst
Copy link
Member

If I have a project that targets netstandard2.0 and I "privately" (transitively) reference an OOB System package that references netstandard2.0, and then the consumer wants to reference that project in a .NET 5 app and have a "public" (top-level) dependency on the .NET 5 OOB reference

Does this describe your setup?

  • Project App [net5.0]
    • Project A [nestandard2.0]
      • NuGet B [nestandard2.0]
        • NuGet System.C [nestandard2.0]

I assume by

OOB System package

You mean a component that is in-box in net5.0 but isn't part of nestandard2.0, correct?

The expectation is that this just works. The application output for App might or might not contain a binary for System.C (that depends on whether System.C special cases net5.0 to give it no files). However, even if the application contains a binary for System.C (for example, because the package doesn't special case net5.0 or because the was built for .NET Core 3.1 but was rolled forward to .NET 5 via a config) then the expectation is that the runtime will load the higher version, which in your case is the in-box version of System.C.

Does this make sense?

@springy76
Copy link

My personal experience when it comes to (transitive) NuGet dependency graphs:
Even if a library can happily live with only netstandard1.x (+ some NuGet references) (or even netstandard2.0) the entire dependency graph becomes much less uglier when multi-targeting against (netstandard2.0 +) netcoreapp3.0 + netcoreapp3.1.. and most likely the same with +net5.0 and +net6.0.
This also has great impact on the amount of files copied to output bin dir.

@jzabroski
Copy link

jzabroski commented Sep 28, 2020

The use of Project/Nuget, bullets and brackets is very useful notation. Thank you.

The set-up I am describing is:

  • Project RuntimeLoadedLibrary [netstandard2.0]
    • Project A [netstandard2.0]
      • NuGet B [netstandard2.0]
        • NuGet System.C [netstandard2.0]
  • Project AppThatLoads_RuntimeLoadedLibrary [net5.0]
    • NuGet System.C [net5.0]

An example of System.C would be System.Data.SqlClient. Is that now in-box for .NET 5? Apologies if I missed that announcement.

The concrete example I've given in the past is TaskRunner.exe and Task.dll. Imagine TaskRunner dynamically discovers ITask { void Execute(); } implementations and has to Activator.CreateInstance that Task and run it. Anything in the Execute call tree then gets lazily loaded by the CLR. When the CLR encounters some assembly version it does not recognize, it throws.

My analysis is that because the just works bits are all done at compile time, that there is no way to co-integrate or goal seek to solve for the right runtime dependencies in the dynamically loaded plug-in. Worse, users don't know what to do when confronted with a cannot find assembly error, because there is no call to action in the exception telling them what to do. Most people go to the open source project author or StackOverflow for help. I could be wrong. I believe, in the old days, people would link against the dependency they expected to be there at run-time, but also bindingRedirect with a wide range, thereby allowing a single interface contract. I think that user story is not quite solved for. The wide version range bindingRedirect was a crappy solution, but it frankly did work a lot nicer for solving this problem then what I am aware of in .NET 5 (ne .NET Core) today.

Note: The key scenario the wide version range bindingRedirect did not handle well in the old days was global tools like MSBuild. For that, you would have to create an IDirtyAssemblyResolveHelper and handle the load event, effectively re-implementing the wide version range bindingRedirect in C#. For that reason, I gave the concrete example of TaskRunner.exe, since it's basically a stripped down version of MSBuild where you write all your targets in C#.

@jzabroski
Copy link

@terrajobst I edited the last post, SORRY. Just replying here so you see that I edited it. I had one typo in the second top-level bullet tree.

@jzabroski
Copy link

jzabroski commented Sep 28, 2020

By the way, I don't think this is fiction. Azure App Services injects the wrong DLL version into application processes when you check SQL Server Monitoring checkbox. How come Azure App Services can't call the MSBuild just works bits as a service?

Note: I express this example because, technically, the workaround I have found for the TaskRunner.exe example is to create a dummy TaskRunnerBase class and have people sub-class it and reference their dynamically loaded library, statically. I colloquially refer to this set-up as "In-Process Tool chaining". It solves the run-time dependency problem by effectively converting the run-time dependency to a compile-time dependency, thus opting into the just works bits. However, in the case of Azure App Service, I can't do this transformation, because I don't own Azure App Service bits.

@jzabroski
Copy link

Even if a library can happily live with only netstandard1.x (+ some NuGet references) (or even netstandard2.0) the entire dependency graph becomes much less uglier when multi-targeting against (netstandard2.0 +) netcoreapp3.0 + netcoreapp3.1.. and most likely the same with +net5.0 and +net6.0.
This also has great impact on the amount of files copied to output bin dir.

@springy76 I'm not sure I understood that. In my experience, multi-targeting makes the code more uglier (but potentially more correct) because it forces you to handle any static failures. An example would be ASP.NET Core testing libraries that are written for ASP.NET Core plug-ins and need to work against multiple versions of the ASP.NET Core framework. The reason why the code being more uglier isn't so bad is that we can then Coverlet our code and see what branches we're not covering across all the different TFM permutations.

The other learning experience I had is that, precisely this problem I described above, which took me forever to figure out the right approach to solving, in part because System.ComponentModel.DataAnnotations OOB package followed insane assembly versioning practices. I assumed netstandard2.0 and net48 would have identical assembly versions. Boy, was that a surprise! It took me my entire 2018 Christmas break to figure that one out.

The last learning experience I had is TFM is mostly irrelevant once you get into C# 7.3 vs C# 8.0 and later discussions. There's no backward compatibility and Visual Studio pretty much eats itself. It creates a weird situation when you want to provide long-term support for a library. I've had situations where I said, "There's no way a .netstandard2.0 customer will ever need to consume this library, so I'll use C# 8.0 since my transitive dependency is async all the way, and the C# 8.0 keywords make that hella easy to read." -- I realize this is now veering a bit off-topic, but it's part of the whole experience.

@springy76
Copy link

That's not quite accurate. .NET Standard hasn't been deprecated

That's why I used quotation marks. I don't know whether "obsolete" would be a better fitting word, but at least it is officially superseded by net5 TFM, according to https://docs.microsoft.com/en-us/dotnet/core/dotnet-five#net-standard :

The net5.0 TFM combines and replaces the netcoreapp and netstandard names.

But I can't tell if the linked document is new or old since 09/02/2020 is totally ambiguous to me: could be September or February.

@svick
Copy link

svick commented Oct 1, 2020

@springy76 That just means that net5.0 is effectively the next version of both netstandard2.0 and netcoreapp3.1. But those older versions are not obsolete or deprecated, especially since .Net Framework is going to be supported forever.

@springy76
Copy link

@svick at least this is the plan. But my reading of https://devblogs.microsoft.com/dotnet/the-future-of-net-standard/#what-you-should-target is tl;dr: leave netstandard behind as soon as possible if you can - or at least multi-target your NuGet packages so you don't shoot consumers using net5 in his foot due to exposal of platform specific features.

@jzabroski
Copy link

especially since .Net Framework is going to be supported forever.

@svick Where was this announced? Thanks.

@terrajobst Should I create a new ticket to cover #859 (comment)

@danmoseley
Copy link
Member

https://devblogs.microsoft.com/dotnet/net-core-is-the-future-of-net/ points out that .NET Framework is supported as part of Windows, and significant parts of Windows itself depend on it.

@trampster
Copy link

.NET Framework isn't going anywhere, but it is going to get harder and harder to get nuget packages that work with it. The nuget packages you depend on will move on and leave you behind.

My latest nuget project JsonSrcGen requires Span so it is .Net Standard 2.1

Because of this it will never support .NET framework. If you can get off .NET Framework you should.

@terrajobst
Copy link
Member

terrajobst commented Oct 2, 2020

@springy76

@svick at least this is the plan. But my reading of https://devblogs.microsoft.com/dotnet/the-future-of-net-standard/#what-you-should-target is tl;dr: leave netstandard behind as soon as possible if you can - or at least multi-target your NuGet packages so you don't shoot consumers using net5 in his foot due to exposal of platform specific features.

No, that wasn't my intent. From my post:

The only reason to retarget from .NET Standard to .NET 5 is to gain access to more runtime features, language features, or APIs. So, you can think of .NET 5 as .NET Standard vNext.

As @svick said: .NET 5 is the successor of .NET Standard 2.1. And the guidance is the same as before: target the lowest version you can. If you must use features that only exist in .NET 5, then you upgrade to .NET 5. If you can get away with targeting .NET Standard 2.0 then you absolutely should because it gives you much more reach.

@terrajobst
Copy link
Member

terrajobst commented Oct 2, 2020

@jzabroski

especially since .Net Framework is going to be supported forever.

@svick Where was this announced? Thanks.

It's part of Scott Hunter's original announcement:

.NET Framework 4.8 will be the last major version of .NET Framework. If you have existing .NET Framework applications that you are maintaining, there is no need to move these applications to .NET Core. We will continue to both service and support .NET Framework, which includes bug–, reliability– and security fixes. It will continue to ship with Windows (much of Windows depends on .NET Framework) and we will continue to improve the tooling support for .NET in Visual Studio (Visual Studio is written on .NET Framework).

It doesn't say forever, but it says as long as Windows is supported which for all intents and purposes is the same thing.

@terrajobst
Copy link
Member

terrajobst commented Oct 2, 2020

@trampster

.NET Framework isn't going anywhere, but it is going to get harder and harder to get nuget packages that work with it. The nuget packages you depend on will move on and leave you behind.

Eventually that is likely a very true statement. But I don't see a mass exodus that quickly. .NET Framework is installed on 1.8 billion machines and there is a lot of code running on top of it that won't move any time soon. Different library authors have different target audiences. Web and mobile developers can leave .NET Framework behind today already. For desktop applications and WCF services that's a different equation, so YMMV.

My latest nuget project JsonSrcGen requires Span so it is .Net Standard 2.1

Because of this it will never support .NET framework. If you can get off .NET Framework you should.

Strictly speaking you don't have to drop .NET Standard 2.0 for span. You can install System.Memory which will give you Span<T> and friends. However, this doesn't give you all the methods in the BCL that accept spans so this might or might not work for you. FWIW, System.Text.Json uses span and works on .NET Standard 2.0 using the System.Memory NuGet package just fine. Span works on top of .NET Framework but there is the caveat that it's not as fast as on .NET Core. But that likely doesn't matter for .NET Framework customers.

@jzabroski
Copy link

@terrajobst Sorry, I didn't see a reply about #859 (comment)

As far as supporting .NET Standard 2.0, I don't know, man. You guys made it really hard by having so many things in C# 8.0 and tying C# 8.0 to .NET Standard 2.1. Supporting .NET Standard 2.0 is pretty challenging when you consider how much simpler .NET Standard 2.1 makes Async All The Way. I might seem like a great engineer, but I just put my head down and work hard to push out solutions I personally love. I'm nowhere near the Big Brain you and Dan are. So, when confronted with .NET Standard 2.0 and .NET Standard 2.1, it will get squeezed out, especially as I'm at the phase of life where I'm starting a family.

But... solving the scenario I pose in #859 (comment) would seriously cut down on support requests I get for two nuget packages each with over 1M downloads. I don't know where these packages rank among open source projects, but they must be very high up there. Like, I love you guys and what you all do for us consumers of .NET, you give me a job indirectly, and for that I am very thankful. But issues like this one I pose in #859 (comment) are just tough to deal with and hard to explain to beginners. Meanwhile, I can see some prominent Microsoft employees on Twitter complain about Node.JS modules taking forever to download and each Node.JS project having 10,000 modules and how .NET Core is so much better and faster, but they miss the point about why people in Node.JS land never have to deal with this time sink called Assembly Load Exception.. I don't know if you've ever read Gilad Bracha's academic paper, "Modules as Objects", but he nailed it. This is what Dart + Flutter does (Google hired him and he got to re-implement that vision in Dart and Flutter, and it;s at the very core of what makes FLutter awesome), this is what JavaScript 6 EcmaScript committee nailed - you can go and read the mailing list and even Allen Wirfs-Brock is on there talking about how to keep JavaScript modules simple and just objects, because you get so much for free with that. I realize you guys were probably optimizing for something else with .NET Core, and I think you achieved that... but the whole world runs on modularity these days. In many ways, I think .NET Core needs to tidy this up. Otherwise, you'll be third place behind JavaScript/TypeScript, Java (which has OSGI and Peter Krien's BND, and may be a useful source of inspiration for how to plug the holes in .NET's module system).

@nbelley
Copy link

nbelley commented Mar 4, 2021

It's just mind boggling that it won't support netstandard 2.1... I'm stuck in a solution where we have a common framework used by Xamarin and a full server app in .net Framework 4.8 and we can't migrate anything to support net core 3+ with netstandard 2.1 in the framework because the framework won't be referenceable by the server app... This is really bad. What should I do? Multi target? Have multiple nuget pacakges? It's for the same app! The goal was to have a center framework that would be useful to every part.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests