RSCG – NetEscapades.EnumGenerators
RSCG – NetEscapades.EnumGenerators
name | NetEscapades.EnumGenerators |
nuget | https://www.nuget.org/packages/NetEscapades.EnumGenerators/ |
link | https://andrewlock.net/netescapades-enumgenerators-a-source-generator-for-enum-performance/ |
author | Andrew Lock |
Running fast tostring and other features for enum
This is how you can use NetEscapades.EnumGenerators .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net7.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="NetEscapades.EnumGenerators" Version="1.0.0-beta08" OutputItemType="Analyzer" ReferenceOutputAssembly="false" PrivateAssets="all" ExcludeAssets="comile;runtime" /> </ItemGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> </Project>
The code that you will use is
var value = InstallType.ShowGUI; Console.WriteLine($"the enum string is {value.ToStringFast()}"); Console.WriteLine($"{InstallType.None.ToStringFast()}"); var flags = AddToCoffee.Milk | AddToCoffee.Sugar; Console.WriteLine(flags.ToStringFast()); Console.WriteLine($"HasFlag(Milk), {flags.HasFlagFast(AddToCoffee.Milk)}"); Console.WriteLine($"HasFlag(Biscuit), {flags.HasFlagFast(AddToCoffee.Biscuit)}"); //check also //InstallTypeExtensions.GetNames //AddToCoffeeExtensions.GetNames
using NetEscapades.EnumGenerators; using System.ComponentModel.DataAnnotations; using System.Xml.Linq; [EnumExtensions] internal enum InstallType { [Display(Name = $"Please use one of the flags of {nameof(InstallType)}")] None= 0, ShowGUI, ShowNoGui, }
using NetEscapades.EnumGenerators; [EnumExtensions] [Flags] internal enum AddToCoffee { None= 0, Milk=1, Sugar=2, Biscuit=4 }
The code that is generated is
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by the NetEscapades.EnumGenerators source generator // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ #nullable enable #if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 using System; #endif /// <summary> /// Extension methods for <see cref="global::AddToCoffee" /> /// </summary> internal static partial class AddToCoffeeExtensions { /// <summary> /// The number of members in the enum. /// This is a non-distinct count of defined names. /// </summary> public const int Length = 4; /// <summary> /// Returns the string representation of the <see cref="global::AddToCoffee"/> value. /// If the attribute is decorated with a <c>[Display]</c> attribute, then /// uses the provided value. Otherwise uses the name of the member, equivalent to /// calling <c>ToString()</c> on <paramref name="value"/>. /// </summary> /// <param name="value">The value to retrieve the string value for</param> /// <returns>The string representation of the value</returns> public static string ToStringFast(this global::AddToCoffee value) => value switch { global::AddToCoffee.None => nameof(global::AddToCoffee.None), global::AddToCoffee.Milk => nameof(global::AddToCoffee.Milk), global::AddToCoffee.Sugar => nameof(global::AddToCoffee.Sugar), global::AddToCoffee.Biscuit => nameof(global::AddToCoffee.Biscuit), _ => value.ToString(), }; /// <summary> /// Determines whether one or more bit fields are set in the current instance. /// Equivalent to calling <see cref="global::System.Enum.HasFlag" /> on <paramref name="value"/>. /// </summary> /// <param name="value">The value of the instance to investigate</param> /// <param name="flag">The flag to check for</param> /// <returns><c>true</c> if the fields set in the flag are also set in the current instance; otherwise <c>false</c>.</returns> /// <remarks>If the underlying value of <paramref name="flag"/> is zero, the method returns true. /// This is consistent with the behaviour of <see cref="global::System.Enum.HasFlag" /></remarks> public static bool HasFlagFast(this global::AddToCoffee value, global::AddToCoffee flag) => flag == 0 ? true : (value & flag) == flag; /// <summary> /// Returns a boolean telling whether the given enum value exists in the enumeration. /// </summary> /// <param name="value">The value to check if it's defined</param> /// <returns><c>true</c> if the value exists in the enumeration, <c>false</c> otherwise</returns> public static bool IsDefined(global::AddToCoffee value) => value switch { global::AddToCoffee.None => true, global::AddToCoffee.Milk => true, global::AddToCoffee.Sugar => true, global::AddToCoffee.Biscuit => true, _ => false, }; /// <summary> /// Returns a boolean telling whether an enum with the given name exists in the enumeration. /// </summary> /// <param name="name">The name to check if it's defined</param> /// <returns><c>true</c> if a member with the name exists in the enumeration, <c>false</c> otherwise</returns> public static bool IsDefined(string name) => IsDefined(name, allowMatchingMetadataAttribute: false); /// <summary> /// Returns a boolean telling whether an enum with the given name exists in the enumeration, /// or if a member decorated with a <c>[Display]</c> attribute /// with the required name exists. /// </summary> /// <param name="name">The name to check if it's defined</param> /// <param name="allowMatchingMetadataAttribute">If <c>true</c>, considers the value of metadata attributes,otherwise ignores them</param> /// <returns><c>true</c> if a member with the name exists in the enumeration, or a member is decorated /// with a <c>[Display]</c> attribute with the name, <c>false</c> otherwise</returns> public static bool IsDefined(string name, bool allowMatchingMetadataAttribute) { return name switch { nameof(global::AddToCoffee.None) => true, nameof(global::AddToCoffee.Milk) => true, nameof(global::AddToCoffee.Sugar) => true, nameof(global::AddToCoffee.Biscuit) => true, _ => false, }; } #if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 /// <summary> /// Returns a boolean telling whether an enum with the given name exists in the enumeration /// </summary> /// <param name="name">The name to check if it's defined</param> /// <returns><c>true</c> if a member with the name exists in the enumeration, <c>false</c> otherwise</returns> public static bool IsDefined(in ReadOnlySpan<char> name) => IsDefined(name, allowMatchingMetadataAttribute: false); /// <summary> /// Returns a boolean telling whether an enum with the given name exists in the enumeration, /// or optionally if a member decorated with a <c>[Display]</c> attribute /// with the required name exists. /// Slower then the <see cref="IsDefined(string, bool)" /> overload, but doesn't allocate memory./> /// </summary> /// <param name="name">The name to check if it's defined</param> /// <param name="allowMatchingMetadataAttribute">If <c>true</c>, considers the value of metadata attributes,otherwise ignores them</param> /// <returns><c>true</c> if a member with the name exists in the enumeration, or a member is decorated /// with a <c>[Display]</c> attribute with the name, <c>false</c> otherwise</returns> public static bool IsDefined(in ReadOnlySpan<char> name, bool allowMatchingMetadataAttribute) { return name switch { ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.None).AsSpan(), global::System.StringComparison.Ordinal) => true, ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Milk).AsSpan(), global::System.StringComparison.Ordinal) => true, ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Sugar).AsSpan(), global::System.StringComparison.Ordinal) => true, ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Biscuit).AsSpan(), global::System.StringComparison.Ordinal) => true, _ => false, }; } #endif /// <summary> /// Converts the string representation of the name or numeric value of /// an <see cref="global::AddToCoffee" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The case-sensitive string representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::AddToCoffee" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::AddToCoffee" />. This parameter is passed uninitialized.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif string? name, out global::AddToCoffee value) => TryParse(name, out value, false, false); /// <summary> /// Converts the string representation of the name or numeric value of /// an <see cref="global::AddToCoffee" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The string representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::AddToCoffee" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::AddToCoffee" />. This parameter is passed uninitialized.</param> /// <param name="ignoreCase"><c>true</c> to read value in case insensitive mode; <c>false</c> to read value in case sensitive mode.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif string? name, out global::AddToCoffee value, bool ignoreCase) => TryParse(name, out value, ignoreCase, false); /// <summary> /// Converts the string representation of the name or numeric value of /// an <see cref="global::AddToCoffee" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The string representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::AddToCoffee" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::AddToCoffee" />. This parameter is passed uninitialized.</param> /// <param name="ignoreCase"><c>true</c> to read value in case insensitive mode; <c>false</c> to read value in case sensitive mode.</param> /// <param name="allowMatchingMetadataAttribute">If <c>true</c>, considers the value included in metadata attributes such as /// <c>[Display]</c> attribute when parsing, otherwise only considers the member names.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif string? name, out global::AddToCoffee value, bool ignoreCase, bool allowMatchingMetadataAttribute) { if (ignoreCase) { switch (name) { case string s when s.Equals(nameof(global::AddToCoffee.None), global::System.StringComparison.OrdinalIgnoreCase): value = global::AddToCoffee.None; return true; case string s when s.Equals(nameof(global::AddToCoffee.Milk), global::System.StringComparison.OrdinalIgnoreCase): value = global::AddToCoffee.Milk; return true; case string s when s.Equals(nameof(global::AddToCoffee.Sugar), global::System.StringComparison.OrdinalIgnoreCase): value = global::AddToCoffee.Sugar; return true; case string s when s.Equals(nameof(global::AddToCoffee.Biscuit), global::System.StringComparison.OrdinalIgnoreCase): value = global::AddToCoffee.Biscuit; return true; case string s when int.TryParse(name, out var val): value = (global::AddToCoffee)val; return true; default: value = default; return false; } } else { switch (name) { case nameof(global::AddToCoffee.None): value = global::AddToCoffee.None; return true; case nameof(global::AddToCoffee.Milk): value = global::AddToCoffee.Milk; return true; case nameof(global::AddToCoffee.Sugar): value = global::AddToCoffee.Sugar; return true; case nameof(global::AddToCoffee.Biscuit): value = global::AddToCoffee.Biscuit; return true; case string s when int.TryParse(name, out var val): value = (global::AddToCoffee)val; return true; default: value = default; return false; } } } #if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 /// <summary> /// Converts the span representation of the name or numeric value of /// an <see cref="global::AddToCoffee" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The span representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::AddToCoffee" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::AddToCoffee" />. This parameter is passed uninitialized.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif in ReadOnlySpan<char> name, out global::AddToCoffee value) => TryParse(name, out value, false, false); /// <summary> /// Converts the span representation of the name or numeric value of /// an <see cref="global::AddToCoffee" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The span representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::AddToCoffee" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::AddToCoffee" />. This parameter is passed uninitialized.</param> /// <param name="ignoreCase"><c>true</c> to read value in case insensitive mode; <c>false</c> to read value in case sensitive mode.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif in ReadOnlySpan<char> name, out global::AddToCoffee value, bool ignoreCase) => TryParse(name, out value, ignoreCase, false); /// <summary> /// Converts the span representation of the name or numeric value of /// an <see cref="global::AddToCoffee" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The span representation of the enumeration name or underlying value to convert</param> /// <param name="result">When this method returns, contains an object of type /// <see cref="global::AddToCoffee" /> whose /// value is represented by <paramref name="result"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::AddToCoffee" />. This parameter is passed uninitialized.</param> /// <param name="ignoreCase"><c>true</c> to read value in case insensitive mode; <c>false</c> to read value in case sensitive mode.</param> /// <param name="allowMatchingMetadataAttribute">If <c>true</c>, considers the value included in metadata attributes such as /// <c>[Display]</c> attribute when parsing, otherwise only considers the member names.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif in ReadOnlySpan<char> name, out global::AddToCoffee result, bool ignoreCase, bool allowMatchingMetadataAttribute) { if (ignoreCase) { switch (name) { case ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.None).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): result = global::AddToCoffee.None; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Milk).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): result = global::AddToCoffee.Milk; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Sugar).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): result = global::AddToCoffee.Sugar; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Biscuit).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): result = global::AddToCoffee.Biscuit; return true; case ReadOnlySpan<char> current when int.TryParse(name, out var numericResult): result = (global::AddToCoffee)numericResult; return true; default: result = default; return false; } } else { switch (name) { case ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.None).AsSpan(), global::System.StringComparison.Ordinal): result = global::AddToCoffee.None; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Milk).AsSpan(), global::System.StringComparison.Ordinal): result = global::AddToCoffee.Milk; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Sugar).AsSpan(), global::System.StringComparison.Ordinal): result = global::AddToCoffee.Sugar; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::AddToCoffee.Biscuit).AsSpan(), global::System.StringComparison.Ordinal): result = global::AddToCoffee.Biscuit; return true; case ReadOnlySpan<char> current when int.TryParse(name, out var numericResult): result = (global::AddToCoffee)numericResult; return true; default: result = default; return false; } } } #endif /// <summary> /// Retrieves an array of the values of the members defined in /// <see cref="global::AddToCoffee" />. /// Note that this returns a new array with every invocation, so /// should be cached if appropriate. /// </summary> /// <returns>An array of the values defined in <see cref="global::AddToCoffee" /></returns> public static global::AddToCoffee[] GetValues() { return new[] { global::AddToCoffee.None, global::AddToCoffee.Milk, global::AddToCoffee.Sugar, global::AddToCoffee.Biscuit, }; } /// <summary> /// Retrieves an array of the names of the members defined in /// <see cref="global::AddToCoffee" />. /// Note that this returns a new array with every invocation, so /// should be cached if appropriate. /// </summary> /// <returns>An array of the names of the members defined in <see cref="global::AddToCoffee" /></returns> public static string[] GetNames() { return new[] { nameof(global::AddToCoffee.None), nameof(global::AddToCoffee.Milk), nameof(global::AddToCoffee.Sugar), nameof(global::AddToCoffee.Biscuit), }; } }
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by the NetEscapades.EnumGenerators source generator // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ #nullable enable #if NETESCAPADES_ENUMGENERATORS_EMBED_ATTRIBUTES namespace NetEscapades.EnumGenerators { /// <summary> /// Add to enums to indicate that extension methods should be generated for the type /// </summary> [global::System.AttributeUsage(global::System.AttributeTargets.Enum)] [global::System.Diagnostics.Conditional("NETESCAPADES_ENUMGENERATORS_USAGES")] #if NET5_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage(Justification = "Generated by the NetEscapades.EnumGenerators source generator.")] #else [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] #endif public class EnumExtensionsAttribute : global::System.Attribute { /// <summary> /// The namespace to generate the extension class. /// If not provided the namespace of the enum will be used /// </summary> public string? ExtensionClassNamespace { get; set; } /// <summary> /// The name to use for the extension class. /// If not provided, the enum name with "Extensions" will be used. /// For example for an Enum called StatusCodes, the default name /// will be StatusCodesExtensions /// </summary> public string? ExtensionClassName { get; set; } } } #endif
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by the NetEscapades.EnumGenerators source generator // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ #nullable enable #if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 using System; #endif /// <summary> /// Extension methods for <see cref="global::InstallType" /> /// </summary> internal static partial class InstallTypeExtensions { /// <summary> /// The number of members in the enum. /// This is a non-distinct count of defined names. /// </summary> public const int Length = 3; /// <summary> /// Returns the string representation of the <see cref="global::InstallType"/> value. /// If the attribute is decorated with a <c>[Display]</c> attribute, then /// uses the provided value. Otherwise uses the name of the member, equivalent to /// calling <c>ToString()</c> on <paramref name="value"/>. /// </summary> /// <param name="value">The value to retrieve the string value for</param> /// <returns>The string representation of the value</returns> public static string ToStringFast(this global::InstallType value) => value switch { global::InstallType.None => "Please use one of the flags of InstallType", global::InstallType.ShowGUI => nameof(global::InstallType.ShowGUI), global::InstallType.ShowNoGui => nameof(global::InstallType.ShowNoGui), _ => value.ToString(), }; /// <summary> /// Returns a boolean telling whether the given enum value exists in the enumeration. /// </summary> /// <param name="value">The value to check if it's defined</param> /// <returns><c>true</c> if the value exists in the enumeration, <c>false</c> otherwise</returns> public static bool IsDefined(global::InstallType value) => value switch { global::InstallType.None => true, global::InstallType.ShowGUI => true, global::InstallType.ShowNoGui => true, _ => false, }; /// <summary> /// Returns a boolean telling whether an enum with the given name exists in the enumeration. /// </summary> /// <param name="name">The name to check if it's defined</param> /// <returns><c>true</c> if a member with the name exists in the enumeration, <c>false</c> otherwise</returns> public static bool IsDefined(string name) => IsDefined(name, allowMatchingMetadataAttribute: false); /// <summary> /// Returns a boolean telling whether an enum with the given name exists in the enumeration, /// or if a member decorated with a <c>[Display]</c> attribute /// with the required name exists. /// </summary> /// <param name="name">The name to check if it's defined</param> /// <param name="allowMatchingMetadataAttribute">If <c>true</c>, considers the value of metadata attributes,otherwise ignores them</param> /// <returns><c>true</c> if a member with the name exists in the enumeration, or a member is decorated /// with a <c>[Display]</c> attribute with the name, <c>false</c> otherwise</returns> public static bool IsDefined(string name, bool allowMatchingMetadataAttribute) { var isDefinedInDisplayAttribute = false; if (allowMatchingMetadataAttribute) { isDefinedInDisplayAttribute = name switch { "Please use one of the flags of InstallType" => true, _ => false, }; } if (isDefinedInDisplayAttribute) { return true; } return name switch { nameof(global::InstallType.None) => true, nameof(global::InstallType.ShowGUI) => true, nameof(global::InstallType.ShowNoGui) => true, _ => false, }; } #if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 /// <summary> /// Returns a boolean telling whether an enum with the given name exists in the enumeration /// </summary> /// <param name="name">The name to check if it's defined</param> /// <returns><c>true</c> if a member with the name exists in the enumeration, <c>false</c> otherwise</returns> public static bool IsDefined(in ReadOnlySpan<char> name) => IsDefined(name, allowMatchingMetadataAttribute: false); /// <summary> /// Returns a boolean telling whether an enum with the given name exists in the enumeration, /// or optionally if a member decorated with a <c>[Display]</c> attribute /// with the required name exists. /// Slower then the <see cref="IsDefined(string, bool)" /> overload, but doesn't allocate memory./> /// </summary> /// <param name="name">The name to check if it's defined</param> /// <param name="allowMatchingMetadataAttribute">If <c>true</c>, considers the value of metadata attributes,otherwise ignores them</param> /// <returns><c>true</c> if a member with the name exists in the enumeration, or a member is decorated /// with a <c>[Display]</c> attribute with the name, <c>false</c> otherwise</returns> public static bool IsDefined(in ReadOnlySpan<char> name, bool allowMatchingMetadataAttribute) { var isDefinedInDisplayAttribute = false; if (allowMatchingMetadataAttribute) { isDefinedInDisplayAttribute = name switch { ReadOnlySpan<char> current when current.Equals("Please use one of the flags of InstallType".AsSpan(), global::System.StringComparison.Ordinal) => true, _ => false, }; } if (isDefinedInDisplayAttribute) { return true; } return name switch { ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.None).AsSpan(), global::System.StringComparison.Ordinal) => true, ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.ShowGUI).AsSpan(), global::System.StringComparison.Ordinal) => true, ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.ShowNoGui).AsSpan(), global::System.StringComparison.Ordinal) => true, _ => false, }; } #endif /// <summary> /// Converts the string representation of the name or numeric value of /// an <see cref="global::InstallType" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The case-sensitive string representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::InstallType" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::InstallType" />. This parameter is passed uninitialized.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif string? name, out global::InstallType value) => TryParse(name, out value, false, false); /// <summary> /// Converts the string representation of the name or numeric value of /// an <see cref="global::InstallType" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The string representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::InstallType" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::InstallType" />. This parameter is passed uninitialized.</param> /// <param name="ignoreCase"><c>true</c> to read value in case insensitive mode; <c>false</c> to read value in case sensitive mode.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif string? name, out global::InstallType value, bool ignoreCase) => TryParse(name, out value, ignoreCase, false); /// <summary> /// Converts the string representation of the name or numeric value of /// an <see cref="global::InstallType" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The string representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::InstallType" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::InstallType" />. This parameter is passed uninitialized.</param> /// <param name="ignoreCase"><c>true</c> to read value in case insensitive mode; <c>false</c> to read value in case sensitive mode.</param> /// <param name="allowMatchingMetadataAttribute">If <c>true</c>, considers the value included in metadata attributes such as /// <c>[Display]</c> attribute when parsing, otherwise only considers the member names.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif string? name, out global::InstallType value, bool ignoreCase, bool allowMatchingMetadataAttribute) { if (allowMatchingMetadataAttribute) { if (ignoreCase) { switch (name) { case string s when s.Equals("Please use one of the flags of InstallType", global::System.StringComparison.OrdinalIgnoreCase): value = global::InstallType.None; return true; default: break; }; } else { switch (name) { case "Please use one of the flags of InstallType": value = global::InstallType.None; return true; default: break; }; } } if (ignoreCase) { switch (name) { case string s when s.Equals(nameof(global::InstallType.None), global::System.StringComparison.OrdinalIgnoreCase): value = global::InstallType.None; return true; case string s when s.Equals(nameof(global::InstallType.ShowGUI), global::System.StringComparison.OrdinalIgnoreCase): value = global::InstallType.ShowGUI; return true; case string s when s.Equals(nameof(global::InstallType.ShowNoGui), global::System.StringComparison.OrdinalIgnoreCase): value = global::InstallType.ShowNoGui; return true; case string s when int.TryParse(name, out var val): value = (global::InstallType)val; return true; default: value = default; return false; } } else { switch (name) { case nameof(global::InstallType.None): value = global::InstallType.None; return true; case nameof(global::InstallType.ShowGUI): value = global::InstallType.ShowGUI; return true; case nameof(global::InstallType.ShowNoGui): value = global::InstallType.ShowNoGui; return true; case string s when int.TryParse(name, out var val): value = (global::InstallType)val; return true; default: value = default; return false; } } } #if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 /// <summary> /// Converts the span representation of the name or numeric value of /// an <see cref="global::InstallType" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The span representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::InstallType" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::InstallType" />. This parameter is passed uninitialized.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif in ReadOnlySpan<char> name, out global::InstallType value) => TryParse(name, out value, false, false); /// <summary> /// Converts the span representation of the name or numeric value of /// an <see cref="global::InstallType" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The span representation of the enumeration name or underlying value to convert</param> /// <param name="value">When this method returns, contains an object of type /// <see cref="global::InstallType" /> whose /// value is represented by <paramref name="value"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::InstallType" />. This parameter is passed uninitialized.</param> /// <param name="ignoreCase"><c>true</c> to read value in case insensitive mode; <c>false</c> to read value in case sensitive mode.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif in ReadOnlySpan<char> name, out global::InstallType value, bool ignoreCase) => TryParse(name, out value, ignoreCase, false); /// <summary> /// Converts the span representation of the name or numeric value of /// an <see cref="global::InstallType" /> to the equivalent instance. /// The return value indicates whether the conversion succeeded. /// </summary> /// <param name="name">The span representation of the enumeration name or underlying value to convert</param> /// <param name="result">When this method returns, contains an object of type /// <see cref="global::InstallType" /> whose /// value is represented by <paramref name="result"/> if the parse operation succeeds. /// If the parse operation fails, contains the default value of the underlying type /// of <see cref="global::InstallType" />. This parameter is passed uninitialized.</param> /// <param name="ignoreCase"><c>true</c> to read value in case insensitive mode; <c>false</c> to read value in case sensitive mode.</param> /// <param name="allowMatchingMetadataAttribute">If <c>true</c>, considers the value included in metadata attributes such as /// <c>[Display]</c> attribute when parsing, otherwise only considers the member names.</param> /// <returns><c>true</c> if the value parameter was converted successfully; otherwise, <c>false</c>.</returns> public static bool TryParse( #if NETCOREAPP3_0_OR_GREATER [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] #endif in ReadOnlySpan<char> name, out global::InstallType result, bool ignoreCase, bool allowMatchingMetadataAttribute) { if (allowMatchingMetadataAttribute) { if (ignoreCase) { switch (name) { case ReadOnlySpan<char> current when current.Equals("Please use one of the flags of InstallType".AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): result = global::InstallType.None; return true; default: break; }; } else { switch (name) { case ReadOnlySpan<char> current when current.Equals("Please use one of the flags of InstallType".AsSpan(), global::System.StringComparison.Ordinal): result = global::InstallType.None; return true; default: break; }; } } if (ignoreCase) { switch (name) { case ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.None).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): result = global::InstallType.None; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.ShowGUI).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): result = global::InstallType.ShowGUI; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.ShowNoGui).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): result = global::InstallType.ShowNoGui; return true; case ReadOnlySpan<char> current when int.TryParse(name, out var numericResult): result = (global::InstallType)numericResult; return true; default: result = default; return false; } } else { switch (name) { case ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.None).AsSpan(), global::System.StringComparison.Ordinal): result = global::InstallType.None; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.ShowGUI).AsSpan(), global::System.StringComparison.Ordinal): result = global::InstallType.ShowGUI; return true; case ReadOnlySpan<char> current when current.Equals(nameof(global::InstallType.ShowNoGui).AsSpan(), global::System.StringComparison.Ordinal): result = global::InstallType.ShowNoGui; return true; case ReadOnlySpan<char> current when int.TryParse(name, out var numericResult): result = (global::InstallType)numericResult; return true; default: result = default; return false; } } } #endif /// <summary> /// Retrieves an array of the values of the members defined in /// <see cref="global::InstallType" />. /// Note that this returns a new array with every invocation, so /// should be cached if appropriate. /// </summary> /// <returns>An array of the values defined in <see cref="global::InstallType" /></returns> public static global::InstallType[] GetValues() { return new[] { global::InstallType.None, global::InstallType.ShowGUI, global::InstallType.ShowNoGui, }; } /// <summary> /// Retrieves an array of the names of the members defined in /// <see cref="global::InstallType" />. /// Note that this returns a new array with every invocation, so /// should be cached if appropriate. /// </summary> /// <returns>An array of the names of the members defined in <see cref="global::InstallType" /></returns> public static string[] GetNames() { return new[] { nameof(global::InstallType.None), nameof(global::InstallType.ShowGUI), nameof(global::InstallType.ShowNoGui), }; } }
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/NetEscapades.EnumGenerators