-
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
[API Proposal]: Enum.GetCount
#110914
Comments
Can you provide examples of this? |
Tagging subscribers to this area: @dotnet/area-system-runtime |
A common situation I've encountered involves state machines for mapping an enum state to an execution delegate. These delegates are preallocated and stored into an array. Then, execution is simply While a dictionary would be more elegant in creation (and would avoid the cast at lookup), it's not as performant as a simple array access. I don't have any code on hand to show, but the general idea looks like this (assuming we control // the actual ordering of the array fill does not matter because ordering of state members is irrelevant for usage
Action<...>[] stateMap = new Action<...>[Enum.GetValues<States>().Length];
stateMap[(int)States.SomeState] = HandleSomeState;
stateMap[(int)States.SomeOtherState] = HandleSomeOtherState;
_stateMap = stateMap; While there's indeed other, more performant, ways of encoding that length, none are as clean as the above. In the above case, one could consider the overhead of getting the values array negligible to the overall performance, but it's still present. In addition, one has to understand why it's written like that. A simple To clarify my original post: I've seen |
My understanding that the new API is proposed in order to eliminate a single gc allocation in e.g. It seems like it creates a short-living array allocation which is not escaped anywhere and then you only need its length. It looks like it should be perfectly handled by escape analysis feature @AndyAyersMS and @hez2010 are currently working on. |
It cannot be handled by escape analysis as it requires the length of the array to be known at compile time. |
Count seems incorrect here, as it assumes that all the values would be under that Count value. |
Not getting why that can't be done with the existing apis exposed. :-) |
That is likely coming in the next version of C#. You will be able to do: public static class EnumExtensions
{
extension(States)
{
public static int Count => ... whatever you want ...;
}
} You'll then be able to do |
Debatable. Enum members are not an ordered collection, so the meaning of "count" there has no impact on the other meanings of count. This API would get you the count of enum members. The meaning of that count is up to the user. You're arguing that the only proper usage is for an order list. Even then, the original purpose of this proposal is exactly for the situations where the members are known to be in order and zero-based.
Please explain. How can the existing APIs help here? Are you suggesting that the code I showed works? Of course! I've done it multiple times. That doesn't mean the proposal is wrong — it's for a different issue. The example I showed was just showing my motivation for making this proposal.
Key word: likely. We've been waiting on extension evolution for literal years. Not to discount it; I want C# to get it right, but saying "don't add an API because we might do something else" is an irrelevant discard. What happens if .NET 10 and C# 14 come and extensions are delayed again? A simple API that gives you the length of an array inside |
It is not just about the allocation, but the mental logic required to understand what that line means. Alternatively, the runtime could intrinsicify |
Intrinsify var values = new UnderlyingType[<CNS_INT>];
values[0] = ...; values[1] = ...; ...
return values; as we know the This will be much easier than introducing a new API. As for |
But you're saying you need it to initialize an array. Which only makes sense if the values are all less than that Count.
This seems too niche then. Why not just write an extension that gets the elements, and asks for .Length then? I'd only want an API for this if it's useful for all the cases where people use enums.
This doesn't seem sufficient. Take a simple example like:
What does .Count return here? If the purpose here is to make an array with an item at each position for each state machine item, then you would want |
Ok. But im' saying that the motivation seems lacking to me. It only makes sense for narrow use cases, and is trivially possible to provide as an extension method (or an extension property in an upcoming C# version). To me, i would prefer it not be in the BCL unless super sensible and relevant to a wide set of cases. |
I disagree. We should not add marginal APIs that start not making much sense initially, and become even less sensible soon afterwards.
Then you use an extension method.
It's not a simple API in my mind. I still don't understand waht the semantics are. And i only have seen one use case, which seems suspect to me. I'd need either a lot more use cases presented or some super high value cases shown to motivate this for me. |
Background and motivation
Quite a few times, it's desirable to get the number of enum members. The only runtime-provided solution involves an array allocation/fill, getting the count of that, then throwing away the array. For example,
Enum.GetValues<T>().Length
(or similar). Sometimes, people will add a_Count
(or similarly named) element at the end of the member list, but this pollutes the member list, and is arguably wrong due to being typed asT
notint
.On GitHub, I see ~900 uses of
Enum.GetX<T>().Length
and ~15k uses ofEnum.GetX(typeof(T)).Length
, many of which are even in @dotnet-provided (usingtypeof(T)
and generics) or @microsoft-provided (usingtypeof(T)
and generics) code.API Proposal
API Usage
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: