-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
The indexer of Span (the Item[int index] or this[int index] property) takes an int instead of a uint like the equivalent on an Array. #28070
Comments
According to the C# spec, the index can be "an expression of type int, uint, long, ulong, or can be implicitly converted to one or more of these types", so it's not that span takes an int instead of a uint, it's that C# allows arrays to be indexed by things other than int as well, and we only have the one overload on span that's int-based. |
Correct. BTW: The runtime-provided indexer methods on arrays take int indices only as well.
|
And, for the sake of completeness, the implementation is slightly bugged at that: dotnet/roslyn#30648. Luckily it affects only MD arrays.
That's perhaps not that relevant as IL instructions like Should this issue be moved to csharplang then? |
I don't believe so. The issue would likely be closed as non-actionable since this isn't something the language can handle. As you indicated, there is no IL instruction for indexing |
I don't think you are in a position to decide what the language can handle or not handle. You didn't even bother to understand the situation and took my side node about IL not having an instruction as evidence that the language can't handle this. Despite obvious evidence that the language already does this for arrays. |
This is because the language doesn't emit an API call in order to access arrays, they are a built-in/primitive type and are accessed directly via IL instructions.
I did not decide that this is something the language should not handle. I said that it would likely be closed as non-actionable. |
I'm not sure what to say. If even after being told that you didn't bother to understand the situation before replying you reply while still not bothering then there is nothing to discuss. I've had quite enough of this already. |
If you are saying you were asking if dotnet/roslyn#30648 should be moved to dotnet/csharplang, that wasn't necessarily immediately clear and this could have been made infinitely simpler by simply stating something along the lines of:
If you are saying it was something else, then I am completely missing it and this would be made simpler if you elaborated rather than leaving people to guess and grab at what you mean if it is obvious there was some form of miscommunication 😄
|
I suggest we leave the issue here, since it's not necessarily any more or less language than it is library/runtime, but have a discussion with the C# language design team about it. cc: @MadsTorgersen I see three main options:
My preference is (2), as it eases moving from arrays to spans and limits the knowledge the language needs about spans (it has some knowledge today, but mostly for the more general ref struct concept). We've also already been adding more overloads for the new Range/Index support. |
Would it be meaningful improvement? |
Not a huge one, but I've now heard several folks asking about this. @eerhardt hit up against this the other day with some ML stuff. |
Would be good to have an example. One reason to use On the other hand, the fact that array indexing can be done using |
In case anyone is interested, here is the ML scenario where I hit this problem:
Previously So previously, when using an array, I could index into the array using a |
Note that this code is equivalent to |
Just looking at the code surrounding the delta, there is a lot of manual |
I can only guess, since it precedes my time working on the project. But reading More info on KeyTypes, it states:
So I assume the reasoning was "we just need an integer. Since order and/or magnitude of the values is not semantically meaningful, neither is the sign of the integer. Therefore - let's not use signed integers." Also - since these KeyType values are used to index into an array, it is explicitly NOT valid to use a negative integer as a value, because if you did have a negative value it would throw when you indexed into the array. However, according to that doc key type specifies:
Which means that all logical indexes must be There may be other considerations though - these are just the first ones that stuck out to me. @TomFinley @Zruty0 and @glebuk might have more insight into why |
Are we realistically likely to make traction on this? I'd personally love to see a uint indexer here as it feels more natural for certain coding patterns. |
Do you believe that one-off solution for just the indexer would be worth it and move the needle enough? I believe that we would need to add uint overloads for number of other methods (including |
I think it would help for interop code or other scenarios where you may already have uint. It avoids a few places where you need to insert casts and while not perfect, it can be done incrementally. |
Sure, that's fine. There's already a critical mass behind what we have shipped. If we were to introduce some theoretical |
If we want to avoid baking special kowledge about Span into the Compiler, this could be driven by an attribute which tells the compiler to add checked casts for higher range integer types to a given parameter. Having extension method indexers would be another possibility... |
Just for fun, I experimented with this in a local branch. The Lines 138 to 144 in 671b2ef
By rewriting this code using
|
I hit this int/uint array/span indexing issue too during work on processor emulator, but probably because I cant figure yet how to place some raw inline array into struct to be able to pin/fix it to obtain damn unsafe pointer for it, instead of safe ref usage and tackling with heap byte array... (want also to share as much code logic in methods/functions possible between C# and C implementation ... quite possible in fact, only some tiny ugly obstacles here) |
The lack of an unsigned indexer for Span makes it exceedingly hard to work with it in interop code. Most win32 APIs work with DWORD (32bit unsigned), so for correctness I usually make a DllImport that matches the signature exactly. However, as soon as you need to work with buffers and buffer lengths, you are pretty much forced to use a signed integer for length, as you otherwise can't work with it in C#. |
This causes a lot of code changes when switching from new Foo[20U] to stackalloc Foo[20U]. Since you can't allocate a negative sized array, it seems that this should take a uint, and not an int.
Note
This issue is a copy of the reported issue on the developer community https://developercommunity.visualstudio.com/content/problem/376789/the-indexer-of-span-the-itemint-index-or-thisint-i.html
The text was updated successfully, but these errors were encountered: