Ecco un esempio in cui i flag sono utili.
Ho un pezzo di codice che genera password (usando un generatore di numeri pseudocasuali crittograficamente sicuro). Il chiamante del metodo sceglie se la password deve contenere lettere maiuscole, minuscole, cifre, simboli di base, simboli estesi, simboli greci, caratteri cirillici e unicode.
Con i flag, chiamare questo metodo è semplice:
var password = this.PasswordGenerator.Generate(
CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);
e può anche essere semplificato in:
var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);
Senza flag, quale sarebbe la firma del metodo?
public byte[] Generate(
bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols,
bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);
chiamato in questo modo:
// 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);
Come notato nei commenti, un altro approccio sarebbe utilizzare una raccolta:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LowercaseLetters,
CharacterSet.UppercaseLetters,
});
Questo è molto più leggibile rispetto al set di true
e false
, ma ha ancora due svantaggi:
Lo svantaggio principale è che, per consentire valori combinati, come CharacterSet.LettersAndDigits
dovresti scrivere qualcosa del genere in Generate()
metodo:
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.
}
probabilmente riscritto in questo modo:
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.
}
Confronta questo con quello che hai usando i flag:
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters)
{
// The password should contain lowercase letters.
}
Il secondo svantaggio è che non è chiaro come si comporterebbe il metodo se chiamato così:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LettersAndDigits, // So digits are requested two times.
});