Aqui está um exemplo quando os sinalizadores são úteis.
Eu tenho um pedaço de código que gera senhas (usando um gerador de números pseudoaleatórios criptograficamente seguro). O chamador do método escolhe se a senha deve ou não conter letras maiúsculas, minúsculas, dígitos, símbolos básicos, símbolos estendidos, símbolos gregos, cirílicos e unicode.
Com sinalizadores, é fácil chamar esse método:
var password = this.PasswordGenerator.Generate(
CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);
e pode até ser simplificado para:
var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);
Sem sinalizadores, qual seria a assinatura do método?
public byte[] Generate(
bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols,
bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);
chamado assim:
// 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);
Conforme observado nos comentários, outra abordagem seria usar uma coleção:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LowercaseLetters,
CharacterSet.UppercaseLetters,
});
Isso é muito mais legível em comparação com o conjunto de true
e false
, mas ainda tem duas desvantagens:
A principal desvantagem é que, para permitir valores combinados, CharacterSet.LettersAndDigits
você escreveria algo assim no Generate()
método:
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.
}
possivelmente reescrito assim:
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.
}
Compare isso com o que você tem usando sinalizadores:
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters)
{
// The password should contain lowercase letters.
}
A segunda desvantagem muito pequena é que não está claro como o método se comportaria se fosse chamado assim:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LettersAndDigits, // So digits are requested two times.
});