代码之家  ›  专栏  ›  技术社区  ›  IAbstract

迭代枚举的其他方法

  •  1
  • IAbstract  · 技术社区  · 15 年前

    最初我有以下几点:

    [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 回复  |  直到 15 年前
        1
  •  1
  •   Dan Tao    15 年前

    你最初的方法是正确的;你只是被 Enum.GetValues 方法。此方法返回特定 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;
            }
        }
    }
    

    实际上,您甚至可以将上述内容抽象为一个方便的扩展方法。 枚举 类型:

    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
        }
    }
    
        2
  •  0
  •   Ben Voigt    15 年前

    简陋低效的方法:

    qflag.ToString().Split('|')
    
    推荐文章