Skip to content

Commit

Permalink
Merge pull request #12 from xin9le/feature/more-compatibility
Browse files Browse the repository at this point in the history
Improves System.Enum compatibility
  • Loading branch information
xin9le committed Jun 28, 2022
2 parents eda2714 + 3120b8f commit 6ea48bf
Show file tree
Hide file tree
Showing 14 changed files with 1,350 additions and 216 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ This library super easy to use like `System.Enum` that is standard of .NET. Look
var values = FastEnum.GetValues<Fruits>();
var names = FastEnum.GetNames<Fruits>();
var name = FastEnum.GetName<Fruits>(Fruits.Apple);
var name = Fruits.Apple.ToName();
var name = Fruits.Apple.FastToString();
var defined = FastEnum.IsDefined<Fruits>(123);
var parse = FastEnum.Parse<Fruits>("Apple");
var tryParse = FastEnum.TryParse<Fruits>("Apple", out var value);
Expand Down Expand Up @@ -77,7 +77,7 @@ class Member<TEnum>
// etc...
}

var member = Fruits.Apple.ToMember();
var member = Fruits.Apple.ToMember()!;
var (name, value) = member; // Supports deconstruction
```

Expand Down
3 changes: 2 additions & 1 deletion src/Benchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
typeof(IsDefinedByteBenchmark),
typeof(IsDefinedEnumBenchmark),
typeof(IsDefinedStringBenchmark),
typeof(ToStringBenchmark),
typeof(ToStringDefinedBenchmark),
typeof(ToStringUndefinedBenchmark),
typeof(DictionaryEnumKeyBenchmark),
typeof(DictionaryInt32KeyBenchmark),
typeof(DictionaryStringKeyBenchmark),
Expand Down
2 changes: 1 addition & 1 deletion src/Benchmarks/Scenarios/GetNameBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public void Setup()


[Benchmark]
public string FastEnum()
public string? FastEnum()
=> _FastEnum.GetName(Value);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using System;
using BenchmarkDotNet.Attributes;
using EnumsNET;
using FastEnumUtility.Benchmarks.Models;
using _FastEnum = FastEnumUtility.FastEnum;

namespace FastEnumUtility.Benchmarks.Scenarios;



public class ToStringBenchmark
public class ToStringDefinedBenchmark
{
private const Fruits Value = Fruits.Pineapple;

Expand All @@ -16,7 +17,8 @@ public class ToStringBenchmark
public void Setup()
{
_ = Enum.GetNames<Fruits>();
_ = _FastEnum.GetValues<Fruits>();
_ = Enums.GetNames<Fruits>();
_ = _FastEnum.GetMembers<Fruits>();
}


Expand All @@ -25,7 +27,12 @@ public string NetCore()
=> Value.ToString();


[Benchmark]
public string EnumsNet()
=> Value.AsString();


[Benchmark]
public string FastEnum()
=> Value.ToName();
=> Value.FastToString();
}
38 changes: 38 additions & 0 deletions src/Benchmarks/Scenarios/ToStringUndefinedBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using BenchmarkDotNet.Attributes;
using EnumsNET;
using FastEnumUtility.Benchmarks.Models;
using _FastEnum = FastEnumUtility.FastEnum;

namespace FastEnumUtility.Benchmarks.Scenarios;



public class ToStringUndefinedBenchmark
{
private const Fruits Value = (Fruits)byte.MaxValue; // undefined value


[GlobalSetup]
public void Setup()
{
_ = Enum.GetNames<Fruits>();
_ = Enums.GetNames<Fruits>();
_ = _FastEnum.GetMembers<Fruits>();
}


[Benchmark(Baseline = true)]
public string NetCore()
=> Value.ToString();


[Benchmark]
public string EnumsNet()
=> Value.AsString();


[Benchmark]
public string FastEnum()
=> Value.FastToString();
}
31 changes: 25 additions & 6 deletions src/FastEnum/FastEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ public static IReadOnlyList<string> GetNames<T>()


/// <summary>
/// Retrieves the name of the constants in a specified enumeration.
/// Retrieves the name of the constant in the specified enumeration type that has the specified value.
/// </summary>
/// <typeparam name="T">Enum type</typeparam>
/// <returns></returns>
/// <param name="value"></param>
/// <returns>A string containing the name of the enumerated constant in enumType whose value is value; or null if no such constant is found.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetName<T>(T value)
public static string? GetName<T>(T value)
where T : struct, Enum
=> GetMember(value).Name;
=> GetMember(value)?.Name;
#endregion


Expand All @@ -81,11 +82,15 @@ public static IReadOnlyList<Member<T>> GetMembers<T>()
/// Retrieves the member information of the constants in a specified enumeration.
/// </summary>
/// <typeparam name="T">Enum type</typeparam>
/// <param name="value"></param>
/// <returns></returns>
/// <exception cref="NotFoundException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Member<T> GetMember<T>(T value)
public static Member<T>? GetMember<T>(T value)
where T : struct, Enum
=> Cache_UnderlyingOperation<T>.UnderlyingOperation.GetMember(ref value);
=> Cache_UnderlyingOperation<T>.UnderlyingOperation.TryGetMember(ref value, out var member)
? member
: null;
#endregion


Expand Down Expand Up @@ -309,4 +314,18 @@ private static bool TryParseName<T>(string name, bool ignoreCase, out T result)
return false;
}
#endregion


#region ToString
/// <summary>
/// Converts the specified value to its equivalent string representation.
/// </summary>
/// <param name="value"></param>
/// <typeparam name="T">Enum type</typeparam>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString<T>(T value)
where T : struct, Enum
=> Cache_UnderlyingOperation<T>.UnderlyingOperation.ToString(ref value);
#endregion
}
56 changes: 43 additions & 13 deletions src/FastEnum/FastEnumExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static partial class FastEnumExtensions
/// <param name="value"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Member<T> ToMember<T>(this T value)
public static Member<T>? ToMember<T>(this T value)
where T : struct, Enum
=> FastEnum.GetMember(value);

Expand All @@ -28,13 +28,25 @@ public static Member<T> ToMember<T>(this T value)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
/// <returns>A string containing the name of the enumerated constant in enumType whose value is value; or null if no such constant is found.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToName<T>(this T value)
public static string? ToName<T>(this T value)
where T : struct, Enum
=> FastEnum.GetName(value);


/// <summary>
/// Converts the specified value to its equivalent string representation.
/// </summary>
/// <param name="value"></param>
/// <typeparam name="T">Enum type</typeparam>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FastToString<T>(this T value)
where T : struct, Enum
=> FastEnum.ToString(value);


/// <summary>
/// Returns an indication whether a constant with a specified value exists in a specified enumeration.
/// </summary>
Expand All @@ -54,17 +66,27 @@ public static bool IsDefined<T>(this T value)
/// <param name="value"></param>
/// <param name="throwIfNotFound"></param>
/// <returns></returns>
/// <exception cref="NotFoundException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string? GetEnumMemberValue<T>(this T value, bool throwIfNotFound = true)
where T : struct, Enum
{
var attr = value.ToMember().EnumMemberAttribute;
if (attr is not null)
return attr.Value;
var member = value.ToMember();
if (throwIfNotFound)
{
if (member is null)
throw new NotFoundException($"Specified value {value} is not defined.");

return throwIfNotFound
? throw new NotFoundException($"{nameof(EnumMemberAttribute)} is not found.")
: default;
var attr = member.EnumMemberAttribute;
if (attr is null)
throw new NotFoundException($"{nameof(EnumMemberAttribute)} is not found.");

return attr.Value;
}
else
{
return member?.EnumMemberAttribute?.Value;
}
}


Expand All @@ -76,6 +98,8 @@ public static bool IsDefined<T>(this T value)
/// <param name="index"></param>
/// <param name="throwIfNotFound"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="NotFoundException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string? GetLabel<T>(this Member<T> member, int index = 0, bool throwIfNotFound = true)
where T : struct, Enum
Expand All @@ -86,9 +110,10 @@ public static bool IsDefined<T>(this T value)
if (member.Labels.TryGetValue(index, out var label))
return label;

return throwIfNotFound
? throw new NotFoundException($"{nameof(LabelAttribute)} that is specified index {index} is not found.")
: default;
if (throwIfNotFound)
throw new NotFoundException($"{nameof(LabelAttribute)} that is specified index {index} is not found.");

return null;
}


Expand All @@ -103,5 +128,10 @@ public static bool IsDefined<T>(this T value)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string? GetLabel<T>(this T value, int index = 0, bool throwIfNotFound = true)
where T : struct, Enum
=> value.ToMember().GetLabel(index, throwIfNotFound);
{
var member = value.ToMember();
if (throwIfNotFound && member is null)
throw new NotFoundException($"Specified value {value} is not defined.");
return member?.GetLabel(index, throwIfNotFound);
}
}

0 comments on commit 6ea48bf

Please sign in to comment.