-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathEnumExtensions.cs
188 lines (175 loc) · 8.61 KB
/
EnumExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
using System.Runtime.InteropServices;
namespace VolumeControl.TypeExtensions
{
/// <summary>
/// Extensions for any <see cref="Enum"/> type.
/// </summary>
public static class EnumExtensions
{
/// <summary>
/// Returns true if <paramref name="e"/> is equal to any <see langword="enum"/> value present in <paramref name="other"/>.
/// </summary>
/// <typeparam name="T">The enum type.</typeparam>
/// <param name="e">The enum instance.</param>
/// <param name="other">Any enumerable of type <typeparamref name="T"/>.</param>
/// <returns>True when <paramref name="e"/> is equal to at least one value from <paramref name="other"/></returns>
public static bool EqualsAny<T>(this T e, IEnumerable<T> other) where T : struct, Enum
{
foreach (T? o in other)
{
if (e.Equals(o))
return true;
}
return false;
}
/// <param name="e">The enum instance.</param>
/// <param name="other">Any number of other enums of type <typeparamref name="T"/>.</param>
/// <inheritdoc cref="EqualsAny{T}(T, IEnumerable{T})"/>
public static bool EqualsAny<T>(this T e, params T[] other) where T : struct, Enum => e.EqualsAny(other.AsEnumerable());
/// <summary>
/// Returns true if <paramref name="e"/> contains any <see langword="enum"/> value present in <paramref name="other"/>.
/// </summary>
/// <typeparam name="T">The enum type.</typeparam>
/// <param name="e">The enum instance.</param>
/// <param name="other">Any enumerable of type <typeparamref name="T"/>.</param>
/// <returns>True when <paramref name="e"/> is equal to at least one value from <paramref name="other"/></returns>
public static bool HasAnyFlag<T>(this T e, IEnumerable<T> other) where T : struct, Enum
{
foreach (T o in other)
{
if (e.HasFlag(o))
return true;
}
return false;
}
/// <param name="e">The enum instance.</param>
/// <param name="other">Any number of other enums of type <typeparamref name="T"/>.</param>
/// <inheritdoc cref="EqualsAny{T}(T, IEnumerable{T})"/>
public static bool HasAnyFlag<T>(this T e, params T[] other) where T : struct, Enum => e.HasAnyFlag(other.AsEnumerable());
/// <summary>
/// Checks if the enum value has all of the specified <paramref name="flags"/> set.
/// </summary>
/// <typeparam name="T">The enum type.</typeparam>
/// <param name="e">(implicit) The enum value to check.</param>
/// <param name="flags">The flags to check.</param>
/// <returns><see langword="true"/> when the enum value has all of the <paramref name="flags"/> set; otherwise, <see langword="false"/>.</returns>
public static bool HasAllFlags<T>(this T e, IEnumerable<T> flags) where T : struct, Enum
{
foreach (T flag in flags)
{
if (!e.HasFlag(flag))
return false;
}
return true;
}
/// <inheritdoc cref="HasAllFlags{T}(T, IEnumerable{T})"/>
public static bool HasAllFlags<T>(this T e, params T[] flags) where T : struct, Enum => e.HasAllFlags((IEnumerable<T>)flags);
/// <summary>
/// Returns the enum value with the specified <paramref name="flag"/> changed.
/// </summary>
/// <typeparam name="T">The type of enum being operated on.</typeparam>
/// <param name="e">(implicit) Enum value to operate on.</param>
/// <param name="flag">The enum value of the flag to set or unset.</param>
/// <param name="state">The specified <paramref name="flag"/> is set when <see langword="true"/> and unset when <see langword="false"/>.</param>
/// <returns>The enum value with the specified <paramref name="flag"/> set to the specified <paramref name="state"/>.</returns>
public static T SetFlagState<T>(this T e, T flag, bool state) where T : struct, Enum
{
var e_v = Convert.ToInt64(e);
if (state)
{
e_v |= Convert.ToInt64(flag);
}
else
{
e_v &= ~Convert.ToInt64(flag);
}
return (T)Enum.ToObject(typeof(T), e_v);
}
/// <summary>
/// Returns the enum value with any number of flags changed.
/// </summary>
/// <typeparam name="T">The type of enum being operated on.</typeparam>
/// <param name="e">(implicit) Enum value to operate on.</param>
/// <param name="flagStates">Any number of flag-state pairs. When state is <see langword="true"/>, the associated flag is set; otherwise when state is <see langword="false"/>, the associated flag is unset.</param>
/// <returns>The enum value with the specified <paramref name="flagStates"/> changed.</returns>
public static T SetFlagStates<T>(this T e, params (T flag, bool state)[] flagStates) where T : struct, Enum
{
var e_v = Convert.ToInt64(e);
foreach ((T flag, bool state) in flagStates)
{
if (state)
{
e_v |= Convert.ToInt64(flag);
}
else
{
e_v &= ~Convert.ToInt64(flag);
}
}
return (T)Enum.ToObject(typeof(T), e_v);
}
/// <summary>
/// Performs an XOR bitwise operation on the enum and the specified <paramref name="value"/>.
/// </summary>
/// <remarks>
/// Intended for use when the actual enum type is not known, such as within a generic method.
/// </remarks>
/// <typeparam name="T">The type of enum being operated on.</typeparam>
/// <param name="e">(implicit) Enum value to operate on.</param>
/// <param name="value">Enum value to operate on.</param>
/// <returns>The result of the bitwise XOR operation.</returns>
public static T Xor<T>(this T e, T value) where T : struct, Enum
{
return (T)Enum.ToObject(typeof(T), Convert.ToInt64(e) ^ Convert.ToInt64(value));
}
/// <summary>
/// Gets a single merged value containing all of the flags in the <paramref name="enumerable"/>.
/// </summary>
/// <typeparam name="T">The type of enum being operated on.</typeparam>
/// <param name="enumerable">(implicit) Enumerable containing enum values of type <typeparamref name="T"/>.</param>
/// <returns>A single enum value containing all of the values in the <paramref name="enumerable"/>.</returns>
public static T GetSingleValue<T>(this IEnumerable<T> enumerable) where T : struct, Enum
{
var result = Convert.ToInt64(default(T));
foreach (var value in enumerable)
{
result |= Convert.ToInt64(value);
}
return (T)Enum.ToObject(typeof(T), result);
}
/// <summary>
/// Checks if the enum value has 0 or 1 bits set in total.
/// </summary>
/// <typeparam name="T">The type of enum being operated on.</typeparam>
/// <param name="e">(implicit) Enum value to operate on.</param>
/// <returns><see langword="true"/> when the enum value is a power of 2; <see langword="false"/>.</returns>
public static bool IsSingleValue<T>(this T e) where T : struct, Enum
{
var e_v = Convert.ToInt64(e);
return e_v == 0 || (e_v & (e_v - 1)) == 0;
}
/// <summary>
/// Gets the flags that are set in the enum value as individual values.
/// </summary>
/// <typeparam name="T">The type of enum being operated on.</typeparam>
/// <param name="e">(implicit) Enum value to operate on.</param>
/// <returns>An array of the flags that were set in the enum value; when no flags were set, the array contains 1 zero value.</returns>
public static T[] GetSingleValues<T>(this T e) where T : struct, Enum
{
var e_v = Convert.ToInt64(e);
if (e_v == 0)
return new[] { e };
List<T> l = new();
for (int i = 0, bit = 0x1, bitCount = 8 * Marshal.SizeOf(Enum.GetUnderlyingType(typeof(T)));
i < bitCount;
++i, bit = (0x1 << i))
{
if ((e_v & bit) != 0)
{
l.Add((T)Enum.ToObject(typeof(T), bit));
}
}
return l.ToArray();
}
}
}