Скажите, что у меня есть функция, которая принимает перечисление, украшенное атрибутом Флагов. Если значение перечисления является комбинацией больше чем одного из перечислимых элементов, как я могу извлечь один из тех элементов наугад? У меня есть следующее, но кажется, что должен быть лучший путь.
[Flags]
enum Colours
{
Blue = 1,
Red = 2,
Green = 4
}
public static void Main()
{
var options = Colours.Blue | Colours.Red | Colours.Green;
var opts = options.ToString().Split(',');
var rand = new Random();
var selected = opts[rand.Next(opts.Length)].Trim();
var myEnum = Enum.Parse(typeof(Colours), selected);
Console.WriteLine(myEnum);
Console.ReadLine();
}
var options = Colours.Blue | Colours.Green;
var matching = Enum.GetValues(typeof(Colours))
.Cast<Colours>()
.Where(c => (options & c) == c) // or use HasFlag in .NET4
.ToArray();
var myEnum = matching[new Random().Next(matching.Length)];
Если вы не возражаете против небольшого приведения типов и ваше перечисление имеет базовый тип int, следующее будет работать и быстро.
var rand = new Random();
const int mask = (int)(Colours.Blue | Colours.Red | Colours.Green);
return (Colours)(mask & (rand.Next(mask) + 1));
Если вы хотите установить только один флаг, вы можете сделать следующее:
var rand = new Random();
return (Colours)(0x1 << (rand.Next(3)));
Вы можете вызвать Enum.GetValues
, чтобы получить массив значений, определенных перечислением, например:
var rand = new Random();
Colors[] allValues = (Colors[])Enum.GetValues(typeof(Colors));
Colors value = allValues[rand.Next(allValues.Length)];
Если я правильно понял, вопрос касается возврата случайного значения перечисления из значения перечисления flags, а не возврата случайного члена из перечисления flags.
[Flags]
private enum Shot
{
Whisky = 1,
Absynthe = 2,
Pochin = 4,
BrainEraser = Whisky | Absynthe | Pochin
}
[Test]
public void Test()
{
Shot myCocktail = Shot.Absynthe | Shot.Whisky;
Shot randomShotInCocktail = GetRandomShotFromCocktail(myCocktail);
}
private static Shot GetRandomShotFromCocktail(Shot cocktail)
{
Random random = new Random();
Shot[] cocktailShots = Enum.GetValues(typeof(Shot)).
Cast<Shot>().
Where(x => cocktail.HasFlag(x)).ToArray();
Shot randomShot = cocktailShots[random.Next(0, cocktailShots.Length)];
return randomShot;
}
Edit
И, очевидно, вы должны проверить, что перечисление является допустимым значением, например:
Shot myCocktail = (Shot)666;
Edit
Simplified