Oto przykład, kiedy flagi są przydatne.
Mam kawałek kodu, który generuje hasła (za pomocą kryptograficznie bezpiecznego generatora liczb pseudolosowych). Osoba wywołująca metodę wybiera, czy hasło powinno zawierać wielkie litery, małe litery, cyfry, symbole podstawowe, symbole rozszerzone, symbole greckie, cyrylicy i Unicode.
W przypadku flag wywołanie tej metody jest łatwe:
var password = this.PasswordGenerator.Generate(
CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);
i można nawet uprościć:
var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);
Bez flag, jaki byłby podpis metody?
public byte[] Generate(
bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols,
bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);
o nazwie tak:
// 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);
Jak zauważono w komentarzach, innym podejściem byłoby użycie kolekcji:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LowercaseLetters,
CharacterSet.UppercaseLetters,
});
Jest to o wiele bardziej czytelne w porównaniu do zestawu true
i false
, ale nadal ma dwie wady:
Główną wadą jest to, że aby umożliwić łączenie wartości, tak CharacterSet.LettersAndDigits
jakbyś pisał coś takiego w Generate()
metodzie:
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.
}
ewentualnie przepisane w ten sposób:
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.
}
Porównaj to z tym, co masz, używając flag:
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters)
{
// The password should contain lowercase letters.
}
Druga, bardzo niewielka wada polega na tym, że nie jest jasne, jak zachowałaby się metoda, gdyby została wywołana w następujący sposób:
var password = this.PasswordGenerator.Generate(
new []
{
CharacterSet.Digits,
CharacterSet.LettersAndDigits, // So digits are requested two times.
});