Aquí hay un ejemplo cuando las banderas son útiles.
Tengo un código que genera contraseñas (usando un generador de números pseudoaleatorios criptográficamente seguro). La persona que llama del método elige si la contraseña debe contener letras mayúsculas, minúsculas, dígitos, símbolos básicos, símbolos extendidos, símbolos griegos, cirílicos y unicode.
Con banderas, llamar a este método es fácil:
var password = this.PasswordGenerator.Generate(
CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);
e incluso se puede simplificar para:
var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);
Sin banderas, ¿cuál sería la firma del método?
public byte[] Generate(
bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols,
bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);
llamado así:
// 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);
Como se señaló en los comentarios, otro enfoque sería utilizar una colección:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LowercaseLetters,
CharacterSet.UppercaseLetters,
});
Esto es mucho más legible en comparación con el conjunto de true
y false
, pero aún tiene dos inconvenientes:
El principal inconveniente es que para permitir valores combinados, como CharacterSet.LettersAndDigits
si estuviera escribiendo algo así en el 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.
}
posiblemente reescrito así:
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 esto con lo que tiene usando banderas:
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters)
{
// The password should contain lowercase letters.
}
El segundo inconveniente menor es que no está claro cómo se comportaría el método si se llama así:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LettersAndDigits, // So digits are requested two times.
});