Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Breaking Change] Improving .NET Core Version APIs #12124

Closed
richlander opened this issue Feb 25, 2019 · 15 comments
Closed

[Breaking Change] Improving .NET Core Version APIs #12124

richlander opened this issue Feb 25, 2019 · 15 comments
Labels
area-System.Runtime breaking-change Issue or PR that represents a breaking API or functional change over a prerelease.
Milestone

Comments

@richlander
Copy link
Member

[Breaking Change] Improving .NET Core Version APIs

We are improving the .NET Core version APIs in .NET Core 3.0. The particular changes we made are technically breaking. The changes are currently only in the master branch, so will be part of .NET Core 3.0 Preview 4, modulo feedback.

Also posted at dotnet/corefx #35573

Related:

Goal

The goal of the improvement is to enable access to accurate and precise product version information, like is displayed in the following example:

C:\testapps\versioninfo>dotnet run
.NET Core version:
Environment.Version: 3.0.0
RuntimeInformation.FrameworkDescription: .NET Core 3.0.0-preview4.19113.15
CoreFX Build: 3.0.0-preview4.19113.15
CoreFX Hash: add4cacbfb7f7d3f5f07630d10b24e38da4ad027

Code: https://gist.github.com/richlander/f5849c6967c66d699301f75101906f99

Existing Behavior

The product (as of .NET Core 3.0 Preview 3) does not provide the version information displayed above, but seemingly arbitrary values, as displayed in the following example (using the same code):

C:\testapps\versioninfo>dotnet run
.NET Core version:
Environment.Version: 4.0.30319.42000
RuntimeInformation.FrameworkDescription: .NET Core 4.6.27415.71
CoreFX Build: 4.7.0-preview4.19113.15
CoreFX Hash: add4cac

Note: These version strings are based on the .NET Framework heritage of the product.

Breaking Change

The change is technically breaking because it resets the versioning scheme of the product as reported by these APIs. Some code somewhere will break, however, we do not expect that to be pervasive. Unfortunately, it will be hard to write code that works with both the new behavior and old behavior given how close the values are.

We should never have shipped .NET Core 1.0 with this behavior to avoid this problem now. We decided that .NET Core 3.0 is likely our last chance to fix these APIs, so decided to take the opportunity now.

Feedback

We would love your feedback.

@jmezach
Copy link
Contributor

jmezach commented Mar 12, 2019

Was it ever a consideration to create a new API for this? Obviously that has pro's and con's, but at least that would allow backporting to earlier versions, right?

@jkotas
Copy link
Member

jkotas commented Mar 12, 2019

would allow backporting to earlier versions

We do not back port new APIs to earlier versions. The only exceptions may be critical bugs like security fixes.

@richlander
Copy link
Member Author

Was it ever a consideration to create a new API for this?

No. We want to avoid a trail of tears of APIs that were once thought to be great and came to disappoint us. Instead, we make carefully considered breaks in major releases. It's a choice, but we think the right choice for the long-term sustainability of the platform. Our roll-forward policy aligns with this approach (no auto roll-forward on major version).

@ww898
Copy link
Contributor

ww898 commented Apr 19, 2019

ICorProfilerInfo3::GetRuntimeInformation() continues returning v4.0.30319 in 3.0.100-preview4-011223. Is that correct? How can I get real CoreCLR version?

@jkotas
Copy link
Member

jkotas commented Apr 19, 2019

ICorProfilerInfo3::GetRuntimeInformation()

Discussed in https://github.com/dotnet/coreclr/issues/22845

@IlyaGrebnov
Copy link

Let's say, I am library developer and want to target my library as .net standard 2.0 and at run-time determinate framework version. For sake of argument, I only care if version is .net core and version >= 3.0

Looks like I can differentiate between .NET Core and Full framework by checking for ".NET Core", but how I can differentiate pre-3.0 from future 4.6+ versions?

Why not make it "NET Core 4.6.27415.71 (2.1.x)", "NET Core 4.6.27415.71 (3.0.0)" and "NET Core 4.6.27415.71 (4.6.x)", etc..

This way it won't be ambiguous.

@richlander
Copy link
Member Author

We have a solution in mind for this problem that we're still working on. Will share shortly.

@richlander
Copy link
Member Author

Looks like I can differentiate between .NET Core and Full framework by checking for ".NET Core", but how I can differentiate pre-3.0 from future 4.6+ versions?

PTAL https://devblogs.microsoft.com/dotnet/introducing-net-5/

@IlyaGrebnov
Copy link

IlyaGrebnov commented May 7, 2019

So this is right way to check for .net core 3.0+?

    private static readonly bool IsNetCore30OrAbove =
        RuntimeInformation.FrameworkDescription.StartsWith(".NET Core", StringComparison.OrdinalIgnoreCase) &&
        !RuntimeInformation.FrameworkDescription.StartsWith(".NET Core 4.6", StringComparison.OrdinalIgnoreCase);

Note, I am a bit sarcastic, because this looks like a hack. Is any better way to do this in NS2?

@danmoseley
Copy link
Member

@richlander is there activity here that is likely to result in this being closed for July 1st? That's the cutoff for zero bugs for 3.0. If not we should move to Future.

@jkotas
Copy link
Member

jkotas commented Jun 10, 2019

Nothing left to do.

@jkotas jkotas closed this as completed Jun 10, 2019
@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the 3.0 milestone Jan 31, 2020
@gitfool
Copy link

gitfool commented Oct 17, 2020

@richlander I'm trying to understand the best way to update existing code that detects .NET Core to add support for .NET 5.0+.

Specifically, looking at the csharp implementation of grpc/grpc in Grpc.Core.Internal.PlatformApis, is it be reasonable to replace:

isNetCore = RuntimeInformation.FrameworkDescription.StartsWith(".NET Core");

with:

isNetCore = RuntimeInformation.FrameworkDescription.StartsWith(".NET Core") ||
    RuntimeInformation.FrameworkDescription.StartsWith(".NET") && Environment.Version.Major >= 5;

If I understand the changes above correctly, this should work for all .NET Core runtimes, past, present and future.

@richlander
Copy link
Member Author

I don't think you need the second RI.FD check.

Check this out: https://gist.github.com/richlander/3f9bd226acaa3c8e080e1945e7407bc3

@jkotas
Copy link
Member

jkotas commented Oct 20, 2020

Also, Environment.Version check can be first to optimize for new runtimes that are eventually going to be the typical case:

isNetCore = Environment.Version.Major >= 5 || RuntimeInformation.FrameworkDescription.StartsWith(".NET Core");

@richlander
Copy link
Member Author

I updated the sample above to align with Jan's feedback and included the specific check.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Runtime breaking-change Issue or PR that represents a breaking API or functional change over a prerelease.
Projects
None yet
Development

No branches or pull requests

8 participants