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

System.Range package similar to System.ValueTuple #28285

Closed
lostmsu opened this issue Dec 29, 2018 · 27 comments · Fixed by #104170
Closed

System.Range package similar to System.ValueTuple #28285

lostmsu opened this issue Dec 29, 2018 · 27 comments · Fixed by #104170
Assignees
Labels
area-System.Runtime design-discussion Ongoing discussion about design without consensus
Milestone

Comments

@lostmsu
Copy link

lostmsu commented Dec 29, 2018

My understanding is System.Range and System.Index are going to be .NET Core 3.0 specific features.
That prevents me from creating a library, that targets .NET Standard 2.0 (for I need to support .NET 4.7), and implements range indexers for the types defined in it.

I think it is a huge problem, especially considering the next .NET Standard is not going to be implemented by .NET 4.8.

Are there any plans to deal with it?

Is the problem in the desire to implement range-based indexing for the core types like System.Array? If so, are there ways to work around that? Can .NET Core 3.0 instead define System._Range, and have hypothetical System.Range package implementing an implicit conversion System._Range -> System.Range? Any other alternatives?

@gfoidl
Copy link
Member

gfoidl commented Dec 29, 2018

Any other alternatives?

You can use multi-targeting. So you have a code path for .NET Core 3.0 and one for .NET Standard 2.0.

@lostmsu
Copy link
Author

lostmsu commented Dec 29, 2018

@gfoidl how would that work? I'd still need a System.ValueTuple-like package for .NET Standard 2.0 for System.Range to implement ranges. Otherwise consumers of my library will face name conflicts with other libraries.

If you are proposing to drop range indexing for .NET Standard 2.0, then that's exactly what I want to avoid.

@gfoidl
Copy link
Member

gfoidl commented Dec 29, 2018

I meant the latter, and don't know a better way.

@eerhardt
Copy link
Member

eerhardt commented Feb 7, 2019

/cc @terrajobst

@joshfree
Copy link
Member

joshfree commented Mar 4, 2019

@tarekgh can you PTAL

@tarekgh
Copy link
Member

tarekgh commented Mar 4, 2019

@lostmsu Index and Range are not in netstandard 2.0. These types will be in netstandard 2.1. You may look at dotnet/standard#1018.

@lostmsu
Copy link
Author

lostmsu commented Mar 4, 2019

@tarekgh , yes, and that is the nature of the problem. The indexing feature of C# 8 will be unusable on .NET Framework.

@eerhardt
Copy link
Member

eerhardt commented Mar 4, 2019

It's not just the indexing feature of C# 8 being available on .NET Framework that I'm concerned about. (There are other C# 8 features that flat out won't ever work on .NET Framework 4.8. See Building C# 8.0 Blog).

But the core issue here is that you can't have a netstandard2.0 or less library that exposes APIs that will allow the indexing feature in C# 8 to work when it IS available (say in a .NET Core 3.0 app).

For example, in the System.Numerics.Tensors library (which targets netstanard1.1 today), we'd like to have a Slice method on a Tensor. Since tensors are multi-dimensional, you need to have a collection of start and stop indices - basically exactly what System.Range is. One for each dimension.

To expose the Slice API, we need some way of specifying the range in each dimension you want to slice off the tensor. Without having System.Range available, Numerics.Tensors will need to come up with their own "Range-like API". Let's say ValueTuple<int, int>. But here's the problem - is the 2nd int a Length or a stopping index? If it is a stopping index, is it inclusive or exclusive? Does it handle negative indices? etc. etc.

All of these problems would be solved if we had a common type that encapsulated these semantics. And we do have the type, we just aren't allowing libraries less than netstandard2.1 use it.

@johnnyasantoss
Copy link

Any updates on a package for Range and Index?

@bgrainger
Copy link
Contributor

In lieu of an official solution, I created my own unofficial one last month:

@tarekgh
Copy link
Member

tarekgh commented Nov 5, 2019

@terrajobst @jaredpar do we have the final call on that?

@tarekgh tarekgh assigned terrajobst and unassigned tarekgh Jan 16, 2020
@msftgits msftgits transferred this issue from dotnet/corefx Feb 1, 2020
@msftgits msftgits added this to the Future milestone Feb 1, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 23, 2020
@RayKoopa
Copy link

RayKoopa commented Jul 2, 2020

Also looking forward to a "backport" NuGet package for ranges in .NET Standard 2.0, just like System.Memory or Microsoft.Bcl.HashCode.

And here I wondered why I never get code style hints by VS for starting to use ranges... was because I also target classic .NET Framework... 👀

@joperezr joperezr removed the untriaged New issue has not been triaged by the area owner label Jul 2, 2020
@joperezr
Copy link
Member

joperezr commented Jul 2, 2020

ping @terrajobst can you please take a look?

@terrajobst
Copy link
Member

I've recently discussed this. The problem is this:

  1. ValueTuple was a bit of disaster. That's because we shipped an out of box (OOB) and in-box version on .NET Framework. This has caused significant pain with binding redirectcs and friends.
  2. Range itself doesn't suffer from this because there is no version of .NET Framework that included it. We don't have any issues with pure OOBs (span, JSON) However, Range depends on tuples 😞

One could maybe argue that (1) is a thing of the past as .NET Framework 4.7 includes it in-box (and we generally recommend to be on 4.7.2 to consume .NET Standard 2.0 binaries). We should test this, but I think an OOB for range seems doable.

@ericstj any other concerns?

@ericstj
Copy link
Member

ericstj commented Jul 21, 2020

I think we've created a pattern with the Microsoft.Bcl additions that solves the technical problems. I briefly looked at @bgrainger's solution and it follows this pattern. There is still the annoyance that the entire stack needs to target the framework with the component inbox to eliminate the need for the package, for example #35984.

@DjArt
Copy link

DjArt commented Jul 18, 2021

That's still actual problem. Any chance to make this happens?

@chucker
Copy link

chucker commented Mar 4, 2022

@DjArt I've just backported a library from .NET 6.0 to .NET Standard 2.0, and one of the things I had to re-add was System.Range. Long story short:

	<PackageReference Include="IndexRange" Version="1.0.0" />

This seemed to do the trick for my relatively simple use case (get a string's characters except for the very first and very last, with [1..^1]). Some more complex needs may not work; see the issues at https://github.com/bgrainger/IndexRange

@saucecontrol
Copy link
Member

I wouldn't hesitate to use @bgrainger's package in an app, but as a library author, I'm more concerned about the likelihood of downstream conflicts if I were to take a dependency on it. Not being an 'official' package, it doesn't show up in places like https://apisof.net/, making it more likely a similar third-party shim or a copy/paste of the BCL source might end up in a consuming project alongside my transitive dependency.

It would be really nice to see an 'official' package for this, if only to avoid such conflicts.

@IanKemp
Copy link

IanKemp commented Jun 17, 2022

@terrajobst @ericstj bump.

@Crono1981
Copy link

Crono1981 commented Oct 14, 2022

This would be a huge help. I have legacy apps I still need to patch from time to time, and the ability to use one code base for both legacy and modern .NET apps is a lifesaver.

I want to adapt to the newer syntax elements but them not being supported in older SDKs makes adoption very complicated.

@gregsdennis
Copy link
Contributor

So I'm guessing this probably isn't coming? It's been a year since any activity here.

@lostmsu
Copy link
Author

lostmsu commented Oct 19, 2023

@gregsdennis the abovementioned package IndexRange does the job.

@gregsdennis
Copy link
Contributor

@lostmsu I'm in the same boat as @saucecontrol. I'm building a library, and I have to consider downstream impacts.

@chucker
Copy link

chucker commented Oct 19, 2023

@gregsdennis @saucecontrol can’t you use PrivateAssets="All" to avoid downstream impact?

@saucecontrol
Copy link
Member

You can't if you expose public APIs with Index or Range arguments, which I do, but FWIW I have been using the IndexRange package for over a year with no reported issues.

@saucecontrol
Copy link
Member

Since it's not yet mentioned here, if you need Index/Range only for internal use (not exposing in public API surface), PolySharp includes those types, along with polyfills for the attribute types required to support modern C# features downlevel.

PolySharp can also make its generated Index/Range public, but then each project's definition of them is distinct. For public APIs, I'd still recommend the IndexRange package, as those types can be shared between projects.

@github-actions github-actions bot locked and limited conversation to collaborators Aug 2, 2024
@ericstj
Copy link
Member

ericstj commented Dec 5, 2024

As of .NET 9.0 release last month this package is now available publicly as Microsoft.BCL.Memory for those who were previously waiting on this please give it a try.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Runtime design-discussion Ongoing discussion about design without consensus
Projects
None yet
Development

Successfully merging a pull request may close this issue.