Aquí hay un ejemplo cuando las banderas son útiles.
Tengo un fragmento de código que genera contraseñas (utilizando un generador de números pseudoaleatorios criptográficamente seguro). La persona que llama al 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 todavía tiene dos inconvenientes:
El principal inconveniente es que para permitir valores combinados, como CharacterSet.LettersAndDigits
, estarías escribiendo algo así en el método 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.
}
posiblemente reescrito de esta manera:
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 utilizando indicadores:
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters)
{
// The password should contain lowercase letters.
}
El segundo inconveniente, muy pequeño, es que no está claro cómo se comportaría el método si se llamara así:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LettersAndDigits, // So digits are requested two times.
});