[Proposal] enum constraint #2889
Replies: 14 comments
-
I don't believe this is true. Generics should never cause boxing. |
Beta Was this translation helpful? Give feedback.
-
IIRC this would require runtime changes as currently the compiler needs to emit different IL depending on the underlying type of the enum. But I agree. The goal of the original language change was to lift the imposed limitation. The goal of this proposal could be to expand on their functionality so that they can be treated as integral enums.
Enums are a weird beast in the runtime. |
Beta Was this translation helpful? Give feedback.
-
To be clear, will this then box? using System;
public class C {
public static void Main() => M(StringComparison.CurrentCulture);
public void M<T>(T t) where T :Enum{
}
} |
Beta Was this translation helpful? Give feedback.
-
This will: using System;
public class C {
public static void Main() => M<Enum>(StringComparison.CurrentCulture);
public void M<T>(T t) where T :Enum{
}
} I don't recall what other scenarios might result in the value being boxed. |
Beta Was this translation helpful? Give feedback.
-
Well yes, but why would you do that? And how does adding the struct constraint help if you do need to do that? |
Beta Was this translation helpful? Give feedback.
-
Prevents you from doing that. :) I don't know of a reason why you'd want to accept |
Beta Was this translation helpful? Give feedback.
-
Meh I don't think we need a language feature to prevent you doing something that there's no reason to do, but which if you do causes a slight performance hit, especially not when you can just add the struct constraint yourself anyway. |
Beta Was this translation helpful? Give feedback.
-
I'd agree. The language (and maybe runtime) feature would be to better support enums in generics so that you can do arithmetic with them, like testing/combining flags and the like. That requires being able to treat those values as integral types, and that requires eliminating |
Beta Was this translation helpful? Give feedback.
-
Context: Unfortunately the CodePlex conversations are archived. |
Beta Was this translation helpful? Give feedback.
-
Actually, the JIT now has special recognition for the methods on the |
Beta Was this translation helpful? Give feedback.
-
Note: there's workaround using System.Runtime.CompilerServices;
public static bool HasAnyFlag<TEnum>(this TEnum @enum, params TEnum[] flags)
{
foreach (var flag in flags)
{
if ((Unsafe.As<TEnum, int>(ref @enum) & Unsafe.As<TEnum, int>(ref flag)) == Unsafe.As<TEnum, int>(ref flag))
return true;
}
return false;
} |
Beta Was this translation helpful? Give feedback.
-
@huoyaoyuan public static bool HasAnyFlag<TEnum>(this TEnum @enum, params TEnum[] flags)
where TEnum : unmanaged, Enum, IConvertible
{
foreach (var flag in flags)
{
if ((@enum.ToInt32(null) & flag.ToInt32(null)) != 0)
return true;
}
return false;
} |
Beta Was this translation helpful? Give feedback.
-
@DaZombieKiller That's not optimized. sharplab |
Beta Was this translation helpful? Give feedback.
-
I've tried this to solve this question: public static bool HasAnyBits<TEnum>(this TEnum enm, TEnum mask) where TEnum : struct, Enum => enm.ToInt64().HasAnyBits(mask.ToInt64());
public static long ToInt64(this Enum enm, bool arithmetical = false) => enm.GetTypeCode() switch
{
TypeCode.Int32 => arithmetical ? (int) (object) enm : (long) unchecked((uint) (int) (object) enm),
TypeCode.UInt32 => (uint) (object) enm,
TypeCode.Int64 => (long) (object) enm,
TypeCode.UInt64 => unchecked((long) (ulong) (object) enm),
TypeCode.Int16 => arithmetical ? (short) (object) enm : (long) unchecked((ushort) (short) (object) enm),
TypeCode.UInt16 => (ushort) (object) enm,
TypeCode.Byte => (byte) (object) enm,
TypeCode.SByte => arithmetical ? (sbyte) (object) enm : (long) unchecked((byte) (sbyte) (object) enm),
_ => throw new ArgumentException("Invalid enum underlying type")
}; But it's too ugly and no optimization to output IL, so finally I can only write an extension method for each enum. That's tooooooo BAD. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Not to be confused with #104
This proposal is to use
enum
keyword as a constraint. Which would be compiled down tounmanaged, Enum
Why? because currently, Enum constrain will box the enum, you can manually combine it with struct to prevent boxing but you still can't stackalloc it, and you can constrain it as well to unmanaged so you can both, avoid boxing and stackalloc, but it would be cool if this constraint was implicit already by just typing
where TEnum : enum
. Also, maybe as well allows us to use bitshift and other operators?This should be perfectly valid, but it isn't... Maybe it would be easier to support this way?
Beta Was this translation helpful? Give feedback.
All reactions