Comment comparer les drapeaux en C #? (partie 2)
Question
drapeaux de bits sont un peu difficile à comprendre:)
Je sais cette et this et je comprends les réponses et j'ai même suivi cette article d'un bon ami la mienne.
Mais je ne peux pas encore la figure dehors quand je dois « evolute » plus que la norme ...
Ce que je suis en train de faire est la suivante:
if (HttpContext.Current.Session["DebugSessionText"] != null)
{
showType = parDebug.Write2LogType.WARN |
parDebug.Write2LogType.ERROR |
parDebug.Write2LogType.INFO;
if (!chkInfo.Checked)
showType &= ~parDebug.Write2LogType.INFO; // remove INFOs
if (!chkError.Checked)
showType &= ~parDebug.Write2LogType.ERROR; // remove ERRORs
List<myDebugRow> list =
(List<myDebugRow>)HttpContext.Current.Session["DebugSessionText"];
gv.DataSource = list.FindAll(x => x.Type == showType));
}
gv.DataBind();
Je dois filtrer un objet de la liste, donc je peux obtenir tout ce que l'utilisateur veut (afficher uniquement les erreurs INFO, exception mais errrors ERREURs de toujours être mise en garde a montré) ...
Yat-il un moyen direct de faire ceci ou je dois filtrer manuellement sans utiliser l'expression LAMBDA?
Merci pour toute l'aide.
La solution
x.Type == showType
vous obtenez seulement les éléments qui correspondent à tous les conditions (drapeaux de bits) exactement. Avec
(x.Type & showType) != 0
Vous trouverez tous les articles qui ont au moins un match 1 bit avec showType, ce qui est probablement ce que vous voulez.
Autres conseils
Si vous trouvez ces opérations de confusion - et franchement, je ne doute - alors considérer le niveau d'upping abstraction. vous écrire quelques méthodes d'extension d'aide.
static WriteToLogType AddWarn(this WriteToLogType x) { return x | WriteToLogType.WARN; }
static WriteToLogType ClearWarn(this WriteToLogType x) { return x & ~WriteToLogType.WARN; }
static bool HasWarn(this WriteToLogType x) { return 0 != (x & WriteToLogType.WARN); }
// same for Error, Info
static bool HasExactly(this WriteToLogType x, WriteToLogType y) { return x == y; }
static bool HasAny(this WriteToLogType x, WriteToLogType y) { return 0 != (x & y); }
static bool HasAll(this WriteToLogType x, WriteToLogType y) { return y == (x & y); }
Et maintenant votre programme devient
showType = WriteToLogType.None.AddWarn().AddInfo().AddError();
if (!chkInfo.Checked) showType = showType.ClearInfo();
if (!chkError.Checked) showType = showType.ClearError();
List<myDebugRow> list = whatever;
gv.DataSource = list.FindAll(x => x.Type.HasAny(showType)));
Ce que j'espère que vous êtes d'accord est beaucoup plus clair que tout ce bit bidouilles. Mais nous pouvons le rendre plus clair encore.
showType = WriteToLogType.None.AddWarn();
if (chkInfo.Checked) showType = showType.AddInfo();
if (chkError.Checked) showType = showType.AddError();
List<myDebugRow> list = whatever;
gv.DataSource = list.FindAll(x => x.Type.HasAny(showType)));
Au lieu d'ajouter un bouquet de drapeaux, puis les enlever, il suffit de ne pas les ajouter en premier lieu.
gv.DataSource = list.FindAll(x => x.Type == showType));
doit être
gv.DataSource = list.FindAll(x => 0 != (x.Type & showType)));
Comme vous ne voulez pas du genre à être exactement ce que showType est, non? Vous pouvez manuellement itérer sur la liste et faire comparer et enlever ce que vous n'avez pas besoin si je ne suis pas sûr que c'est une solution élégante.