Skip to content

Behavioral differences with System.Enum #14

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

Open
TylerBrinkley opened this issue Oct 6, 2017 · 2 comments
Open

Behavioral differences with System.Enum #14

TylerBrinkley opened this issue Oct 6, 2017 · 2 comments

Comments

@TylerBrinkley
Copy link
Owner

TylerBrinkley commented Oct 6, 2017

When creating this library, I deliberately tried to make the API and behavior as close to System.Enum's as possible in order for it to be a drop in replacement as well as allowing Enums.NET to be the basis for improvements to System.Enum in corefx as has been proposed with corefx#15453.

There are however a few behavioral differences that either snuck in or were made deliberately. If corefx#15453 gets implemented I will like to update Enums.NET to a new major version which fixes most of these behavioral differences.

API Enums.NET Behavior System.Enum Behavior Proposed Solution
GetNames Names are returned in increasing order by their respective values Names are returned in increasing significance bit order by their respective values Add an EnumMemberSelection.ValueOrder flag enum member
GetValues Values are returned in increasing value order Values are returned in increasing significance bit order Add an EnumMemberSelection.ValueOrder flag enum member
GetMembers Members are returned in increasing order by their respective values Members will be returned in increasing significance bit order by their respective values Add an EnumMemberSelection.ValueOrder flag enum member
ToObject Throws OverflowException when value is outside the underlying type's value range Allows overflowing values Rework EnumValidation enum and add an EnumValidation.NoOverflow flag enum member. EnumValidation.None, EnumValidation.IsDefined, and EnumValidation.IsValidFlagCombination will have new meanings such that they no longer validate there were no overflows.
AsString and Format with flags For flags, if the value is not defined then each of it's individual flags are output For flags, the defined combinations within the value with the largest values are output until their are no more flags left to output Hard break in Enums.NET. To get the same behavior as before you'll need to replace it with something like this. value.IsValidFlagCombination() ? string.Join(", ", value.GetFlagMembers().Select(flag => flag.Name) : value.AsString()

Additionally, more research must be done to determine the behavioral differences for the following methods with their accepted value types and the exceptions they throw.

  • Format(Type enumType, object value, string format)
  • GetName(Type enumType, object value)
  • IsDefined(Type enumType, object value)

Other potential breaking changes if corefx#15453 gets implemented

  • Change EnumsNET.PrimaryEnumMemberAttribute to System.ComponentModel.PrimaryAttribute.
  • Switch to using System.ComponentModel.AttributeCollection and then add appropriate extension methods to support the existing methods on EnumsNET.AttributeCollection in older versions of System.ComponentModel.AttributeCollection. This will mean in older framework targets the attribute collection will not explicitly implement IList<Attribute> or IReadOnlyList<Attribute> as is currently the case but will support being casted to those interfaces as the returned attribute collection will derive from System.ComponentModel.AttributeCollection for older framework targets.
  • Change GetAllFlags to AllFlags as in the proposal.
  • IsValidFlagCombination will be promoted to an extension method in older framework targets.
  • The existing extension methods that are covered in the proposal will be demoted in newer framework targets so users will be encouraged to use the new built-in extension methods and not cause any overload resolution conflicts.
  • Remove EnumMember in newer framework targets that already contain the built-in EnumMember and use that instead.
@yyjdelete
Copy link

yyjdelete commented Jul 24, 2020

Add another edge case.

EnumsNET.Enums.GetNames(Type) and maybe all other non-generic methods will throw
System.InvalidOperationException: Cannot perform late binding operation on fields of the type whose Type.ContainsGenericParameters is True. for any open gereric types
, because GetValue failed and unable to create an value of open generic type.

UDPATE: Cache<>.Instance didn't work for field on open type.

System.Enum.GetValues(Type) failed with System.NotSupportedException: Unable to create an open type array., but seems all other static method will success.

public class XXX<T> { public enum X1 { A = 1} }
EnumsNET.Enums.GetNames(typeof(XXX<>.X1))

@TylerBrinkley
Copy link
Owner Author

That's an interesting edge case I never considered. I'd imagine the fact that System.Enum supported that case was by happenstance and not by design and I wouldn't trust that it would remain supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants