Редактировать : Этот пост не является дубликатом, другие решения не позволяют использовать побитовые операторы.
Я хочу сделать что-то вроде этого:
public static class EnumExt
{
public static enum AddFlag(this enum e, enum flag) => e |= flag;
}
Так что я могу использовать это так:
Color color = Red;
color.AddFlag(Color.Dark);
Это немного легче читать. И Я хочу, чтобы этот единственный метод работал для всех значений перечисления, вместо того, чтобы делать переопределение для каждого, с которым я планирую работать. Проблема в том, что код не будет работать, потому что enum
не является типа как int
есть. Я пытался сделать что-то с дженериками:
public static class EnumExt
{
public static T AddFlag<T>(this T e, T flag)
where T : Enum // Can't constrain to Enum
{
return e = e | flag;
}
}
и это:
public static T AddFlag<T>(this T e, T flag)
where T : struct
{
if (!(typeof(T).IsEnum)) return default;
return e |= flag; // Operator '|' cannot be applied to T
}
У которого есть две проблемы. Поскольку это struct
, это означает, что этот метод будет отображаться для значений int
. Я использую struct
только потому, что это самое близкое ограничение к Enum
. Я выхожу из метода, если это не Enum
, но это все еще не дает компилятору понять, что e
- это enum
, даже если это всегда должно быть в этой точке.
Также пытались использовать where T : int
и использовать приведение, но int
является недопустимым ограничением.
Есть ли в любом случае это можно сделать?
РЕДАКТИРОВАТЬ : Я попробовал два ответа, которые были предложены как решение проблемы, но они этого не делают. Тот, у которого IEnumConstraint
не работает, потому что говорит, что мой enum
не наследуется от него, и ни один из ответов не позволяет мне на самом деле return e |= flag;
// Doesn't work because C# won't allow bitwise operators on generic types
// Because the constraint is still vague enough for non-enum values to slip through
public static T AddFlag<T>(this T e, T flag)
where T : struct, IConvertible
// Doesn't work because enums don't inherit from IEnumConstraint
// Same as above
public static T AddFlag<T>(this T e, T flag)
where T : struct, IEnumConstraint
Я предполагаю, что, даже если они ограничены только значениями Enum
, некоторые другие классы все еще могут наследовать от IEnumConstraint
и IConvertible
, поэтому побитовые операторы не будут работать, поскольку гарантия того, что операция будет доступна для T
.
Кажется, единственное реальное решение - в C # 7.3, где они позволяют использовать System.Enum
в качестве ограничения.