2022 鐵人賽文 搬回點部落
開始試煉
Flag Enum 如果還不知道是啥的話 請先看下面的文章
目前我看過最棒的了 說明得非常清楚
C#: 位元旗標 (Bit flag) 與列舉
其實在用Flag Enum時都會搭配tools
提供這組擴充方法 給大家參考
Enum Flag Extensions
用權限當範例
一個Role有哪些權限 搭配Flag Enum是很適合的 這樣記錄到DB只需要開一個欄位
用Enum Flag Extensions當基底寫一個範例code
只要有好工具 Flag Enum 超好用的
void Main()
{
// start with a value
PermissionTypes permissions = PermissionTypes.Read | PermissionTypes.Write;
//then check for the values
bool canRead = permissions.Has(PermissionTypes.Read).Dump("canRead");
bool canWrite = permissions.Has(PermissionTypes.Write).Dump("canWrite");
bool canDelete = permissions.Has(PermissionTypes.Delete).Dump("canDelete");
permissions.Has(PermissionTypes.Delete).Dump("permissions.Has(PermissionTypes.Delete)");
var p2 = permissions.Include(PermissionTypes.Delete);
p2.Has(PermissionTypes.Delete).Dump("p2.Has(PermissionTypes.Delete)");
var p3 = permissions.Remove(PermissionTypes.Delete);
p3.Has(PermissionTypes.Delete).Dump("p3.Has(PermissionTypes.Delete)");
p3.Missing(PermissionTypes.Delete).Dump("p3.Missing(PermissionTypes.Delete)");
}
[Flags]
internal enum PermissionTypes
{
None = 0,
Read = 1,
Write = 2,
Modify = 4,
Delete = 8,
Create = 16,
All = Read | Write | Modify | Delete | Create
}
public static class EnumExtensions
{
/// <summary>
/// Includes an enumerated type and returns the new value
/// </summary>
public static T Include<T>(this Enum value, T append)
{
Type type = value.GetType();
// determine the values
object result = value;
var parsed = new Value(append, type);
if (parsed.Signed != null)
{
result = Convert.ToInt64(value) | (long)parsed.Signed;
}
// return the final value
return (T)Enum.Parse(type, result.ToString());
}
/// <summary>
/// Removes an enumerated type and returns the new value
/// </summary>
public static T Remove<T>(this Enum value, T remove)
{
Type type = value.GetType();
// determine the values
object result = value;
var parsed = new Value(remove, type);
if (parsed.Signed != null)
{
result = Convert.ToInt64(value) & ~(long)parsed.Signed;
}
// return the final value
return (T)Enum.Parse(type, result.ToString());
}
/// <summary>
/// Checks if an enumerated type contains a value
/// </summary>
public static bool Has<T>(this Enum value, T check)
{
Type type = value.GetType();
//determine the values
var parsed = new Value(check, type);
return parsed.Signed != null &&
(Convert.ToInt64(value) & (long)parsed.Signed) == (long)parsed.Signed;
}
/// <summary>
/// Checks if an enumerated type is missing a value
/// </summary>
public static bool Missing<T>(this Enum obj, T value)
{
return !Has(obj, value);
}
/// <summary>
/// Internal class to simplfy narrowing values between a
/// ulong and long since either value should cover any
/// lesser value.
/// </summary>
private class Value
{
public readonly long? Signed;
// cached comparisons for tye to use
private static readonly Type _uInt64 = typeof(ulong);
private static readonly Type _uInt32 = typeof(long);
public Value(object value, Type type)
{
//make sure it is even an enum to work with
if (!type.IsEnum)
{
throw new
ArgumentException("Value provided is not an enumerated type!");
}
//then check for the enumerated value
Type compare = Enum.GetUnderlyingType(type);
//if this is an unsigned long then the only
//value that can hold it would be a ulong
if (compare == _uInt32 || compare == _uInt64)
{
Unsigned = Convert.ToUInt64(value);
}
//otherwise, a long should cover anything else
else
{
Signed = Convert.ToInt64(value);
}
}
public ulong? Unsigned { get; set; }
}
}
結束試煉
Flag Enum 熟練後 可是神兵利器阿
參考
小章哥 滿滿的範例
C#.NET 二進制運算 Enum of Flags
如果內容有誤請多鞭策謝謝