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
Indexer of the IEnumerable #1642
Comments
Because VB allows it: https://github.com/dotnet/vblang/blob/master/spec/expressions.md#default-query-indexer
Because C# has no equivalent rule.
The compilers/languages are working as spec'ed. If you have a proposal on a change you'd like to see here, you can def make one :) Note: my guess is that this would not be accepted. Generally, c# recommends that if you have an indexer it actually operate in |
Holy crap, I didn't know you could use an What's worse is that it uses |
C# will only compile Thanks. |
So this would be a language feature that would literally violate one of the guidelines we have for how the language should behave with APIs. |
@CyrusNajmabadi |
You can ask CoreFx that :) However, my guess would be 'no'. For the same reasons that C# would not want to give it. It would make people think it was fsat/cheap to index into an IEnumerable. And, it's really not. -- For example, say your stream has 1m+ elements in it. If you access Having an operator which people thinks runs sublinearly actually be linear is a very big foot-gun. |
Note: if we ever get Extension Everything, then you can easily add this yourself by providing an extension indexer on IEnumerable. That way any perf issues can be contained to your own projects. but it's doubtful that C# would ever add this into the language itself. I also doubt CoreFx would do it. But you're welcome to ask them. However, that should be in their repo, not here. |
@CyrusNajmabadi |
VB.NET is about writting code easily and quickly. But I agree with you that it shout use ElemntAt not ElementAtOrDefault. |
It's an interface. there's no way to know how it's implemented :) For example, here's a totally reasonable implementation of an IEnumerable: class CyEnumerable : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
int i = 0;
while (true)
{
yield return i++;
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
} If you do for (int i = 0; i < whatever; i++)
{
var v = stream[i];
} For iteration 5 it will need to enumerate 5 elements. Then on iteration 10 it will need to enumerate 10 elements. Iteration 100 will need to enumerate 100 elements. etc. etc. So you have:
This is equal to |
IEnumerables are just streams of data. For all one knows, they may be infinite (like the example i gave) If you want a (probably) realized, indexable sequence of data, you can just use IReadOnlyList. If you want a definitely realised, indexable sequence of data, just use List. |
@MohammadHamdyGhanem
An
And correctly. Indexing into an enumerable is not correct. It gives the impression that it can be done easily and efficiently, and that's far from a guarantee that can be made. The fact that it'll then return the default value if you exceed the bounds of the enumeration is just insult to injury. I personally find there to be nothing wrong with using one of LINQ's built-in methods for obtaining a particular value from an enumerable. It makes the developer acknowledge what they're doing. |
Correct. That's a virtue (it allows so many differing implementations and can represent so many types of streams of data), but it's also a drawback (things may be expensive and you dont' know what the actual impl is). If those virtues outweigh the drawbacks for you, then use IEnumerable. If they don't, then use a more appropriate interface/type for your domain specific problem :) |
Yup. So decisions made there may not necessarily apply to C#. C#, in particular, feels like this is a massive footgun that really should be avoided. If people want to index in this manner, just use the actual methods. They're clear and self-documenting and show the user (i.e. you) were totally aware of what you were doing and what sort of behavior/experience you would be getting. |
@CyrusNajmabadi
We get IEnumerable from LinQ. I'm not sure this can be changed. |
You can convert any result into a value that better fits your domain needs. For example, you can call "ToList" or "ToArray" on a result.
Right, because Linq-to-objects works with streams of data (including lazily-created, infinite streams). So, if you're using those, it's best ot be explicit about using .ElementAt so that your code is very clear that it could be doing incredibly expensive stuff. If you want to be able to easily index, then just convert the IEnumerable you get back from linq to another collection type that offers cheap and simple indexing. |
In VB.NET, I can use this code:
The equivalent C# code is:
Why can I use
result(0)
in VB but can't useresult[0]
in C#?Can this be fixed?
The text was updated successfully, but these errors were encountered: