Другой метод для итерации перечисления - PullRequest
1 голос
/ 19 сентября 2010

Изначально у меня было следующее:

[Flags]
public enum QueryFlag
{
    None = 0x00,
    CustomerID = 0x01,
    SalesPerson = 0x02,
    OrderDate = 0x04
}

Поскольку флажки отмечены / сняты, я бы добавил / убрал флаги из:

QueryFlag qflag;

Моя идея - когда пользователь нажимаетКнопка поиска, я бы итерировал фактические флаги, установленные в qflag, чтобы изменить предложение .Where в моем LINQ to Sql.Однако Enum.GetValues(qflag.GetType()) возвращает все значения самого QueryFlag.Не полезно.

Мое решение:

class myForm : Form
{
    List<QueryFlag> qflag = new List<QueryFlag>();

    private void chkOrderDate_CheckedChanged(object sender, EventArgs e)
    {
        if (chkOrderDate.Checked && !qflags.Contains(QueryFlag.OrderDate))
            qflags.Add(QueryFlag.OrderDate);
        else
            qflags.Remove(QueryFlag.OrderDate);
    }

    private void cmdSearch_Click(object sender, EventArgs e)
    {
        if (qflags.Count == 0)
        {
            rtfLog.AppendText("\nNo search criteria selected.");
            return;
        }

        foreach (QueryFlag flag in qflag)
        {
            rtfLog.AppendText(string.Format("\nSearching {0}", flag.ToString()));

            // add switch for flag value
        }
    }
}

public enum QueryFlag
{
    CustomerID,
    SalesPerson,
    OrderDate
}

У меня есть 3 флажка, и на данный момент это работает без каких-либо проблем.Но мне интересно, есть ли лучший способ выполнить эту итерацию.

Ответы [ 2 ]

1 голос
/ 19 сентября 2010

То, как вы это делали изначально, было правильным;ты только что испортил метод Enum.GetValues.Этот метод возвращает каждое определенное значение для определенного типа enum, да.Итак, что вы делаете с этим, проверяете каждое определенное значение против вашего определенного enum значения, чтобы увидеть, установлено ли определенное значение в вашем значении.

То есть, вы должны сделать следующее:

private void chkOrderDate_CheckedChanged(object sender, EventArgs e)
{
    if (chkOrderDate.Checked)
    {
        qFlag |= QueryFlag.OrderDate;
    }
    else
    {
        qFlag &= (~QueryFlag.OrderDate);
    }
}

... и аналогично для других ваших флажков.Затем, когда вы захотите перечислить, какие флаги вы установили:

static IEnumerable<QueryFlag> GetFlags(QueryFlag flags)
{
    foreach (QueryFlag flag in Enum.GetValues(typeof(QueryFlag)))
    {
        // Presumably you don't want to include None.
        if (flag == QueryFlag.None)
        {
            continue;
        }

        if ((flags & flag) == flag)
        {
            yield return flag;
        }
    }
}

Фактически, вы можете даже абстрагировать вышеприведенное в удобный метод расширения для всех enum типов:

public static class FlagsHelper
{
    // This is not exactly perfect, as it allows you to call GetFlags on any
    // struct type, which will throw an exception at runtime if the type isn't
    // an enum.
    public static IEnumerable<TEnum> GetFlags<TEnum>(this TEnum flags)
        where TEnum : struct
    {
        // Unfortunately this boxing/unboxing is the easiest way
        // to do this due to C#'s lack of a where T : enum constraint
        // (there are ways around this, but they involve some
        // frustrating code).
        int flagsValue = (int)(object)flags;

        foreach (int flag in Enum.GetValues(typeof(TEnum)))
        {
            if ((flagsValue & flag) == flag)
            {
                // Once again: an unfortunate boxing/unboxing
                // due to the lack of a where T : enum constraint.
                yield return (TEnum)(object)flag;
            }
        }
    }
}

Ваш обработчик cmdSearch_Click может выглядеть так:

private void cmdSearch_Click(object sender, EventArgs e)
{
    if (qFlag == QueryFlags.None)
    {
        rtfLog.AppendText("\nNo search criteria selected.");
        return;
    }

    foreach (QueryFlag flag in qFlag.GetFlags())
    {
        rtfLog.AppendText(string.Format("\nSearching {0}", flag.ToString()));

        // add switch for flag value
    }
}
0 голосов
/ 19 сентября 2010

Короткий, сырный и неэффективный способ:

qflag.ToString().Split('|')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...