Вот пример, когда флаги полезны.
У меня есть кусок кода, который генерирует пароли (используя криптографически безопасный генератор псевдослучайных чисел). Вызывающий метод выбирает, должен ли пароль содержать заглавные буквы, строчные буквы, цифры, базовые символы, расширенные символы, греческие символы, кириллицу и юникод.
С флагами вызвать этот метод легко:
var password = this.PasswordGenerator.Generate(
CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);
и это может быть даже упрощено до:
var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);
Без флагов, какой будет подпись метода?
public byte[] Generate(
bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols,
bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);
называется так:
// Very readable, isn't it?
// Tell me just by looking at this code what symbols do I want to be included?
var password = this.PasswordGenerator.Generate(
true, true, true, false, false, false, false, false);
Как отмечено в комментариях, другим подходом будет использование коллекции:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LowercaseLetters,
CharacterSet.UppercaseLetters,
});
Это гораздо более читабельно по сравнению с набором true
и false
, но все же имеет два недостатка:
Основным недостатком является то, что для того, чтобы разрешить объединенные значения, как CharacterSet.LettersAndDigits
вы пишете что-то вроде этого в Generate()
методе:
if (set.Contains(CharacterSet.LowercaseLetters) ||
set.Contains(CharacterSet.Letters) ||
set.Contains(CharacterSet.LettersAndDigits) ||
set.Contains(CharacterSet.Default) ||
set.Contains(CharacterSet.All))
{
// The password should contain lowercase letters.
}
возможно переписать так:
var lowercaseGroups = new []
{
CharacterSet.LowercaseLetters,
CharacterSet.Letters,
CharacterSet.LettersAndDigits,
CharacterSet.Default,
CharacterSet.All,
};
if (lowercaseGroups.Any(s => set.Contains(s)))
{
// The password should contain lowercase letters.
}
Сравните это с тем, что у вас есть, используя флаги:
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters)
{
// The password should contain lowercase letters.
}
Второй, очень незначительный недостаток заключается в том, что неясно, как будет вести себя метод, если вызываться так:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LettersAndDigits, // So digits are requested two times.
});