이 열거 형이 있다고 가정 해 봅시다.
[Flags]
enum Letters
{
A = 1,
B = 2,
C = 4,
AB = A | B,
All = A | B | C,
}
예를 들어 AB
설정되어 있는지 확인하려면 다음을 수행하십시오.
if((letter & Letters.AB) == Letters.AB)
결합 플래그 상수의 플래그가 다음보다 설정되어 있는지 확인하는 간단한 방법이 있습니까?
if((letter & Letters.A) == Letters.A || (letter & Letters.B) == Letters.B)
예를 들어와 &
무언가 를 바꿀 수 있습니까?
이진 바이너리에 관해서는 너무 안정적이지 않습니다 …
답변
AB에 문자가 있는지 확인하려면 AND & 연산자를 사용해야합니다 . 다음과 같은 것 :
if ((letter & Letters.AB) != 0)
{
// Some flag (A,B or both) is enabled
}
else
{
// None of them are enabled
}
답변
.NET 4에서는 Enum.HasFlag 메서드를 사용할 수 있습니다 .
using System;
[Flags] public enum Pet {
None = 0,
Dog = 1,
Cat = 2,
Bird = 4,
Rabbit = 8,
Other = 16
}
public class Example
{
public static void Main()
{
// Define three families: one without pets, one with dog + cat and one with a dog only
Pet[] petsInFamilies = { Pet.None, Pet.Dog | Pet.Cat, Pet.Dog };
int familiesWithoutPets = 0;
int familiesWithDog = 0;
foreach (Pet petsInFamily in petsInFamilies)
{
// Count families that have no pets.
if (petsInFamily.Equals(Pet.None))
familiesWithoutPets++;
// Of families with pets, count families that have a dog.
else if (petsInFamily.HasFlag(Pet.Dog))
familiesWithDog++;
}
Console.WriteLine("{0} of {1} families in the sample have no pets.",
familiesWithoutPets, petsInFamilies.Length);
Console.WriteLine("{0} of {1} families in the sample have a dog.",
familiesWithDog, petsInFamilies.Length);
}
}
예제는 다음 출력을 표시합니다.
// 1 of 3 families in the sample have no pets.
// 2 of 3 families in the sample have a dog.
답변
나는 확장 메소드를 사용하여 다음과 같은 것을 작성합니다.
if (letter.IsFlagSet(Letter.AB))
...
코드는 다음과 같습니다.
public static class EnumExtensions
{
private static void CheckIsEnum<T>(bool withFlags)
{
if (!typeof(T).IsEnum)
throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName));
if (withFlags && !Attribute.IsDefined(typeof(T), typeof(FlagsAttribute)))
throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName));
}
public static bool IsFlagSet<T>(this T value, T flag) where T : struct
{
CheckIsEnum<T>(true);
long lValue = Convert.ToInt64(value);
long lFlag = Convert.ToInt64(flag);
return (lValue & lFlag) != 0;
}
public static IEnumerable<T> GetFlags<T>(this T value) where T : struct
{
CheckIsEnum<T>(true);
foreach (T flag in Enum.GetValues(typeof(T)).Cast<T>())
{
if (value.IsFlagSet(flag))
yield return flag;
}
}
public static T SetFlags<T>(this T value, T flags, bool on) where T : struct
{
CheckIsEnum<T>(true);
long lValue = Convert.ToInt64(value);
long lFlag = Convert.ToInt64(flags);
if (on)
{
lValue |= lFlag;
}
else
{
lValue &= (~lFlag);
}
return (T)Enum.ToObject(typeof(T), lValue);
}
public static T SetFlags<T>(this T value, T flags) where T : struct
{
return value.SetFlags(flags, true);
}
public static T ClearFlags<T>(this T value, T flags) where T : struct
{
return value.SetFlags(flags, false);
}
public static T CombineFlags<T>(this IEnumerable<T> flags) where T : struct
{
CheckIsEnum<T>(true);
long lValue = 0;
foreach (T flag in flags)
{
long lFlag = Convert.ToInt64(flag);
lValue |= lFlag;
}
return (T)Enum.ToObject(typeof(T), lValue);
}
public static string GetDescription<T>(this T value) where T : struct
{
CheckIsEnum<T>(false);
string name = Enum.GetName(typeof(T), value);
if (name != null)
{
FieldInfo field = typeof(T).GetField(name);
if (field != null)
{
DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
return attr.Description;
}
}
}
return null;
}
}
답변
답변
HasFlag () 메서드를 사용하는 것보다 .NET 4 이상을 사용할 수있는 경우
예
letter.HasFlag(Letters.A | Letters.B) // both A and B must be set
와 동일
letter.HasFlag(Letters.AB)
답변
정말 귀찮다면 다음과 같은 함수를 작성할 수 있습니다.
public bool IsSet(Letters value, Letters flag)
{
return (value & flag) == flag;
}
if (IsSet(letter, Letters.A))
{
// ...
}
// If you want to check if BOTH Letters.A and Letters.B are set:
if (IsSet(letter, Letters.A & Letters.B))
{
// ...
}
// If you want an OR, I'm afraid you will have to be more verbose:
if (IsSet(letter, Letters.A) || IsSet(letter, Letters.B))
{
// ...
}
답변
예를 들어 AB가 설정되어 있는지 확인하려면 다음과 같이하십시오.
if ((문자 및 Letters.AB) == Letters.AB)
결합 플래그 상수의 플래그가 다음보다 설정되어 있는지 확인하는 간단한 방법이 있습니까?
이 있는지 검사 모두 다른 플래그 여부와 B가 설정되고, 무시가 설정된다.
if((letter & Letters.A) == Letters.A || (letter & Letters.B) == Letters.B)
이 검사 중 A 또는 B가 설정되고, 무시는 다른 플래그가 설정되어 있는지의 여부.
다음과 같이 단순화 할 수 있습니다.
if(letter & Letters.AB)
이진 연산을위한 C는 다음과 같습니다. 이것을 C #에 적용하는 것이 간단해야합니다.
enum {
A = 1,
B = 2,
C = 4,
AB = A | B,
All = AB | C,
};
int flags = A|C;
bool anything_and_a = flags & A;
bool only_a = (flags == A);
bool a_and_or_c_and_anything_else = flags & (A|C);
bool both_ac_and_anything_else = (flags & (A|C)) == (A|C);
bool only_a_and_c = (flags == (A|C));
덧붙여서, 질문의 예에서 변수의 이름은 단수의 ‘letter’입니다. 이것은 단일 문자만을 의미 할 수도 있습니다. 예제 코드는 가능한 문자 세트와 여러 값이 허용됨을 분명히하므로 변수 ‘letters’의 이름을 바꾸는 것이 좋습니다.