Skip to content

Commit 1ce2a88

Browse files
Update for 5.0.0 (#49)
* Update for 5.0.0 * Small cleanup * Update workflow * More updates * Cleanup readme * Small tweak
1 parent 6ef93d0 commit 1ce2a88

File tree

75 files changed

+12742
-13350
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+12742
-13350
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ jobs:
1717
- name: Build
1818
run: dotnet build --configuration Release --no-restore
1919
working-directory: ./Src
20-
- name: Test .NET 4.5
21-
run: dotnet test -f net45 --no-restore --verbosity normal
20+
- name: Test .NET 4.8
21+
run: dotnet test -f net48 --no-restore --verbosity normal
2222
working-directory: ./Src
23-
- name: Test .NET 7
24-
run: dotnet test -f net7 --no-restore --verbosity normal
23+
- name: Test .NET 8
24+
run: dotnet test -f net8 --no-restore --verbosity normal
2525
working-directory: ./Src

README.md

Lines changed: 57 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,19 @@
33
[![NuGet Downloads](https://img.shields.io/nuget/dt/Enums.NET.svg?logo=nuget)](https://www.nuget.org/packages/Enums.NET/)
44
[![Build status](https://img.shields.io/azure-devops/build/tydude4christ/Public/2.svg?logo=azuredevops)](https://dev.azure.com/tydude4christ/Public/_build?definitionId=2)
55

6+
## v5.0 Changes
7+
Removed `Boolean` enum support and dropped support for net45 and bumped it to net461 due to updating dependencies. Also dropped support for netstandard 1.x tfms for similar reasons. Added a net7 target which utilizes the built-in generic number interfaces. Also added an `EnumValidatorAttribute` base class since generic attributes are now supported.
8+
69
## v4.0 Changes
710
Removed `NonGenericEnums`, `NonGenericFlagEnums`, `UnsafeEnums`, and `UnsafeFlagEnums` classes which were deprecated in v3.0 and also removed all other deprecated methods in an effort to slim the library size down. It is recommended if upgrading from 2.x and below to update to 3.x first and follow the warnings to migrate any code that's using deprecated methods and classes. Also, a dependency on the `System.Runtime.CompilerServices.Unsafe` package was added for the .NET 4.5 target in order to remove a build dependency on `Fody`.
811

9-
## v3.0 Changes
10-
One of the major changes for v3.0 is the deprecation of the `NonGenericEnums`, `NonGenericFlagEnums`, `UnsafeEnums`, and `UnsafeFlagEnums` classes whose methods have been added to the `Enums` and `FlagEnums` classes to better match `System.Enum` and provide better discoverability. To help you migrate your code to using the new methods I have created the C# roslyn analyzer [`Enums.NET.Analyzer`](https://www.nuget.org/packages/Enums.NET.Analyzer/) which provides a code fix to migrate your usages of the non-generic and unsafe methods to the new methods.
11-
1212
# Enums.NET
13-
Enums.NET is a high-performance type-safe .NET enum utility library which provides many operations as convenient extension methods. It is compatible with .NET Framework 4.5+ and .NET Standard 1.0+.
13+
Enums.NET is a high-performance type-safe .NET enum utility library which provides many operations as convenient extension methods. It is compatible with .NET Framework 4.6.1+ and .NET Standard 2.0+.
1414

1515
## What's wrong with `System.Enum`
16-
1. Nearly all of `Enum`'s static methods are non-generic leading to the following issues.
17-
* Requires the enum type to be explicitly specified as an argument and requires invocation using static method syntax such as `Enum.IsDefined(typeof(ConsoleColor), value)` instead of what should be `value.IsDefined()`.
18-
* Requires casting/unboxing for methods with an enum return value, eg. `ToObject`, `Parse`, and `GetValues`.
19-
* Requires boxing for methods with enum input parameters losing type-safety, eg. `IsDefined` and `GetName`.
20-
2. Support for flag enums is limited to just the `HasFlag` method which isn't type-safe, is inefficient, and is ambiguous as to whether it determines if the value has all or any of the specified flags. It's all by the way.
21-
3. Most of its methods use reflection on each call without any sort of caching causing poor performance.
22-
4. The pattern to associate extra data with an enum member using `Attribute`s is not supported and instead requires users to manually retrieve the `Attribute`s via reflection. This pattern is commonly used on enum members with the `DescriptionAttribute`, `EnumMemberAttribute`, and `DisplayAttribute`.
16+
1. Support for flag enums is limited to just the `HasFlag` method which isn't type-safe~, is inefficient,~ and is ambiguous as to whether it determines if the value has all or any of the specified flags. It's all by the way.
17+
2. Most of its methods use reflection on each call without any sort of caching causing poor performance.
18+
3. The pattern to associate extra data with an enum member using `Attribute`s is not supported and instead requires users to manually retrieve the `Attribute`s via reflection. This pattern is commonly used on enum members with the `DescriptionAttribute`, `EnumMemberAttribute`, and `DisplayAttribute`.
2319

2420
Enums.NET solves all of these issues and more.
2521

@@ -29,15 +25,14 @@ Enums.NET solves all of these issues and more.
2925
using System;
3026
using System.Linq;
3127
using EnumsNET;
32-
using NUnit.Framework;
28+
using Xunit;
3329
using DescriptionAttribute = System.ComponentModel.DescriptionAttribute;
3430

35-
[TestFixture]
3631
class EnumsNETDemo
3732
{
3833
// Enum definitions at bottom
3934
40-
[Test]
35+
[Fact]
4136
public void Enumerate()
4237
{
4338
var count = 0;
@@ -49,7 +44,7 @@ class EnumsNETDemo
4944
AttributeCollection attributes = member.Attributes;
5045
++count;
5146
}
52-
Assert.AreEqual(8, count);
47+
Assert.Equal(8, count);
5348

5449
count = 0;
5550
// Retrieves distinct values in increasing value order
@@ -59,100 +54,100 @@ class EnumsNETDemo
5954
AttributeCollection attributes = value.GetAttributes();
6055
++count;
6156
}
62-
Assert.AreEqual(6, count);
57+
Assert.Equal(6, count);
6358
}
6459

65-
[Test]
60+
[Fact]
6661
public void FlagEnumOperations()
6762
{
6863
// HasAllFlags
69-
Assert.IsTrue((DaysOfWeek.Monday | DaysOfWeek.Wednesday | DaysOfWeek.Friday).HasAllFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
70-
Assert.IsFalse(DaysOfWeek.Monday.HasAllFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
64+
Assert.True((DaysOfWeek.Monday | DaysOfWeek.Wednesday | DaysOfWeek.Friday).HasAllFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
65+
Assert.False(DaysOfWeek.Monday.HasAllFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
7166

7267
// HasAnyFlags
73-
Assert.IsTrue(DaysOfWeek.Monday.HasAnyFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
74-
Assert.IsFalse((DaysOfWeek.Monday | DaysOfWeek.Wednesday).HasAnyFlags(DaysOfWeek.Friday));
68+
Assert.True(DaysOfWeek.Monday.HasAnyFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
69+
Assert.False((DaysOfWeek.Monday | DaysOfWeek.Wednesday).HasAnyFlags(DaysOfWeek.Friday));
7570

7671
// CombineFlags ~ bitwise OR
77-
Assert.AreEqual(DaysOfWeek.Monday | DaysOfWeek.Wednesday, DaysOfWeek.Monday.CombineFlags(DaysOfWeek.Wednesday));
78-
Assert.AreEqual(DaysOfWeek.Monday | DaysOfWeek.Wednesday | DaysOfWeek.Friday, FlagEnums.CombineFlags(DaysOfWeek.Monday, DaysOfWeek.Wednesday, DaysOfWeek.Friday));
72+
Assert.Equal(DaysOfWeek.Monday | DaysOfWeek.Wednesday, DaysOfWeek.Monday.CombineFlags(DaysOfWeek.Wednesday));
73+
Assert.Equal(DaysOfWeek.Monday | DaysOfWeek.Wednesday | DaysOfWeek.Friday, FlagEnums.CombineFlags(DaysOfWeek.Monday, DaysOfWeek.Wednesday, DaysOfWeek.Friday));
7974

8075
// CommonFlags ~ bitwise AND
81-
Assert.AreEqual(DaysOfWeek.Monday, DaysOfWeek.Monday.CommonFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
82-
Assert.AreEqual(DaysOfWeek.None, DaysOfWeek.Monday.CommonFlags(DaysOfWeek.Wednesday));
76+
Assert.Equal(DaysOfWeek.Monday, DaysOfWeek.Monday.CommonFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
77+
Assert.Equal(DaysOfWeek.None, DaysOfWeek.Monday.CommonFlags(DaysOfWeek.Wednesday));
8378

8479
// RemoveFlags
85-
Assert.AreEqual(DaysOfWeek.Wednesday, (DaysOfWeek.Monday | DaysOfWeek.Wednesday).RemoveFlags(DaysOfWeek.Monday));
86-
Assert.AreEqual(DaysOfWeek.None, (DaysOfWeek.Monday | DaysOfWeek.Wednesday).RemoveFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
80+
Assert.Equal(DaysOfWeek.Wednesday, (DaysOfWeek.Monday | DaysOfWeek.Wednesday).RemoveFlags(DaysOfWeek.Monday));
81+
Assert.Equal(DaysOfWeek.None, (DaysOfWeek.Monday | DaysOfWeek.Wednesday).RemoveFlags(DaysOfWeek.Monday | DaysOfWeek.Wednesday));
8782

8883
// GetFlags, splits out the individual flags in increasing significance bit order
8984
var flags = DaysOfWeek.Weekend.GetFlags();
90-
Assert.AreEqual(2, flags.Count);
91-
Assert.AreEqual(DaysOfWeek.Sunday, flags[0]);
92-
Assert.AreEqual(DaysOfWeek.Saturday, flags[1]);
85+
Assert.Equal(2, flags.Count);
86+
Assert.Equal(DaysOfWeek.Sunday, flags[0]);
87+
Assert.Equal(DaysOfWeek.Saturday, flags[1]);
9388
}
9489

95-
[Test]
96-
public new void ToString()
90+
[Fact]
91+
public void AsString()
9792
{
9893
// AsString, equivalent to ToString
99-
Assert.AreEqual("Equals", NumericOperator.Equals.AsString());
100-
Assert.AreEqual("-1", ((NumericOperator)(-1)).AsString());
94+
Assert.Equal("Equals", NumericOperator.Equals.AsString());
95+
Assert.Equal("-1", ((NumericOperator)(-1)).AsString());
10196

10297
// GetName
103-
Assert.AreEqual("Equals", NumericOperator.Equals.GetName());
104-
Assert.IsNull(((NumericOperator)(-1)).GetName());
98+
Assert.Equal("Equals", NumericOperator.Equals.GetName());
99+
Assert.Null(((NumericOperator)(-1)).GetName());
105100

106101
// Get description
107-
Assert.AreEqual("Is", NumericOperator.Equals.AsString(EnumFormat.Description));
108-
Assert.IsNull(NumericOperator.LessThan.AsString(EnumFormat.Description));
102+
Assert.Equal("Is", NumericOperator.Equals.AsString(EnumFormat.Description));
103+
Assert.Null(NumericOperator.LessThan.AsString(EnumFormat.Description));
109104

110105
// Get description if applied, otherwise the name
111-
Assert.AreEqual("LessThan", NumericOperator.LessThan.AsString(EnumFormat.Description, EnumFormat.Name));
106+
Assert.Equal("LessThan", NumericOperator.LessThan.AsString(EnumFormat.Description, EnumFormat.Name));
112107
}
113108

114-
[Test]
109+
[Fact]
115110
public void Validate()
116111
{
117112
// Standard Enums, checks is defined
118-
Assert.IsTrue(NumericOperator.LessThan.IsValid());
119-
Assert.IsFalse(((NumericOperator)20).IsValid());
113+
Assert.True(NumericOperator.LessThan.IsValid());
114+
Assert.False(((NumericOperator)20).IsValid());
120115

121116
// Flag Enums, checks is valid flag combination or is defined
122-
Assert.IsTrue((DaysOfWeek.Sunday | DaysOfWeek.Wednesday).IsValid());
123-
Assert.IsFalse((DaysOfWeek.Sunday | DaysOfWeek.Wednesday | ((DaysOfWeek)(-1))).IsValid());
117+
Assert.True((DaysOfWeek.Sunday | DaysOfWeek.Wednesday).IsValid());
118+
Assert.False((DaysOfWeek.Sunday | DaysOfWeek.Wednesday | ((DaysOfWeek)(-1))).IsValid());
124119

125120
// Custom validation through IEnumValidatorAttribute<TEnum>
126-
Assert.IsTrue(DayType.Weekday.IsValid());
127-
Assert.IsTrue((DayType.Weekday | DayType.Holiday).IsValid());
128-
Assert.IsFalse((DayType.Weekday | DayType.Weekend).IsValid());
121+
Assert.True(DayType.Weekday.IsValid());
122+
Assert.True((DayType.Weekday | DayType.Holiday).IsValid());
123+
Assert.False((DayType.Weekday | DayType.Weekend).IsValid());
129124
}
130125

131-
[Test]
126+
[Fact]
132127
public void CustomEnumFormat()
133128
{
134129
EnumFormat symbolFormat = Enums.RegisterCustomEnumFormat(member => member.Attributes.Get<SymbolAttribute>()?.Symbol);
135-
Assert.AreEqual(">", NumericOperator.GreaterThan.AsString(symbolFormat));
136-
Assert.AreEqual(NumericOperator.LessThan, Enums.Parse<NumericOperator>("<", ignoreCase: false, symbolFormat));
130+
Assert.Equal(">", NumericOperator.GreaterThan.AsString(symbolFormat));
131+
Assert.Equal(NumericOperator.LessThan, Enums.Parse<NumericOperator>("<", ignoreCase: false, symbolFormat));
137132
}
138133

139-
[Test]
134+
[Fact]
140135
public void Attributes()
141136
{
142-
Assert.AreEqual("!=", NumericOperator.NotEquals.GetAttributes().Get<SymbolAttribute>().Symbol);
143-
Assert.IsTrue(Enums.GetMember<NumericOperator>("GreaterThanOrEquals").Attributes.Has<PrimaryEnumMemberAttribute>());
144-
Assert.IsFalse(NumericOperator.LessThan.GetAttributes().Has<DescriptionAttribute>());
137+
Assert.Equal("!=", NumericOperator.NotEquals.GetAttributes().Get<SymbolAttribute>().Symbol);
138+
Assert.True(Enums.GetMember<NumericOperator>("GreaterThanOrEquals").Attributes.Has<PrimaryEnumMemberAttribute>());
139+
Assert.False(NumericOperator.LessThan.GetAttributes().Has<DescriptionAttribute>());
145140
}
146141

147-
[Test]
142+
[Fact]
148143
public void Parsing()
149144
{
150-
Assert.AreEqual(NumericOperator.GreaterThan, Enums.Parse<NumericOperator>("GreaterThan"));
151-
Assert.AreEqual(NumericOperator.NotEquals, Enums.Parse<NumericOperator>("1"));
152-
Assert.AreEqual(NumericOperator.Equals, Enums.Parse<NumericOperator>("Is", ignoreCase: false, EnumFormat.Description));
145+
Assert.Equal(NumericOperator.GreaterThan, Enums.Parse<NumericOperator>("GreaterThan"));
146+
Assert.Equal(NumericOperator.NotEquals, Enums.Parse<NumericOperator>("1"));
147+
Assert.Equal(NumericOperator.Equals, Enums.Parse<NumericOperator>("Is", ignoreCase: false, EnumFormat.Description));
153148

154-
Assert.AreEqual(DaysOfWeek.Monday | DaysOfWeek.Wednesday, Enums.Parse<DaysOfWeek>("Monday, Wednesday"));
155-
Assert.AreEqual(DaysOfWeek.Tuesday | DaysOfWeek.Thursday, FlagEnums.ParseFlags<DaysOfWeek>("Tuesday | Thursday", ignoreCase: false, delimiter: "|"));
149+
Assert.Equal(DaysOfWeek.Monday | DaysOfWeek.Wednesday, Enums.Parse<DaysOfWeek>("Monday, Wednesday"));
150+
Assert.Equal(DaysOfWeek.Tuesday | DaysOfWeek.Thursday, FlagEnums.ParseFlags<DaysOfWeek>("Tuesday | Thursday", ignoreCase: false, delimiter: "|"));
156151
}
157152

158153
enum NumericOperator
@@ -208,10 +203,9 @@ class EnumsNETDemo
208203
Holiday = 4
209204
}
210205

211-
[AttributeUsage(AttributeTargets.Enum)]
212-
class DayTypeValidatorAttribute : Attribute, IEnumValidatorAttribute<DayType>
206+
class DayTypeValidatorAttribute : EnumValidatorAttribute<DayType>
213207
{
214-
public bool IsValid(DayType value) => value.GetFlagCount(DayType.Weekday | DayType.Weekend) == 1 && FlagEnums.IsValidFlagCombination(value);
208+
public override bool IsValid(DayType value) => value.GetFlagCount(DayType.Weekday | DayType.Weekend) == 1 && FlagEnums.IsValidFlagCombination(value);
215209
}
216210
}
217211
```

Src/Enums.NET.MemoryUsageTest/Enums.NET.MemoryUsageTest.csproj

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>net461;netcoreapp3.1;net5.0</TargetFrameworks>
5+
<TargetFrameworks>net48;net8</TargetFrameworks>
6+
<LangVersion>latest</LangVersion>
67
</PropertyGroup>
78

89
<ItemGroup>
9-
<PackageReference Include="FastEnum" Version="1.5.3" />
10-
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net45" Version="1.0.3">
11-
<PrivateAssets>all</PrivateAssets>
12-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
13-
</PackageReference>
14-
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net461" Version="1.0.3">
10+
<PackageReference Include="FastEnum" Version="1.8.0" />
11+
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net48" Version="1.0.3">
1512
<PrivateAssets>all</PrivateAssets>
1613
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1714
</PackageReference>

Src/Enums.NET.MemoryUsageTest/Program.cs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
11
using System;
22
using System.Diagnostics;
33
using System.Linq;
4+
using EnumsNET;
5+
using EnumsNET.MemoryUsageTest;
46

5-
namespace EnumsNET.MemoryUsageTest
7+
var enumTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(assembly => assembly.GetTypes()).Where(type => type.IsEnum && !type.IsGenericType).ToList();
8+
var methodInfo = typeof(Enums).GetMethod("GetUnderlyingType", []);
9+
var genericMethods = enumTypes.Select(enumType => methodInfo.MakeGenericMethod(enumType)).ToList();
10+
using (new OperationTimer("All Available Enums Caching Performance"))
611
{
7-
static class Program
12+
foreach (var genericMethod in genericMethods)
13+
//foreach (var enumType in enumTypes)
814
{
9-
static void Main()
10-
{
11-
var enumTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(assembly => assembly.GetTypes()).Where(type => type.IsEnum && !type.IsGenericType).ToList();
12-
var methodInfo = typeof(Enums).GetMethod("GetUnderlyingType", Array.Empty<Type>());
13-
var genericMethods = enumTypes.Select(enumType => methodInfo.MakeGenericMethod(enumType)).ToList();
14-
using (new OperationTimer("All Available Enums Caching Performance"))
15-
{
16-
foreach (var genericMethod in genericMethods)
17-
//foreach (var enumType in enumTypes)
18-
{
19-
genericMethod.Invoke(null, null);
20-
//Enums.GetUnderlyingType(enumType);
21-
}
22-
}
23-
Console.WriteLine(enumTypes.Count);
24-
Console.ReadLine();
25-
}
15+
genericMethod.Invoke(null, null);
16+
//Enums.GetUnderlyingType(enumType);
2617
}
18+
}
19+
Console.WriteLine(enumTypes.Count);
20+
Console.ReadLine();
2721

22+
namespace EnumsNET.MemoryUsageTest
23+
{
2824
// This class is useful for doing operation performance timing
2925
internal sealed class OperationTimer : IDisposable
3026
{

0 commit comments

Comments
 (0)