【问题标题】:C# Enum Flag - two ways binding - enum - class -enumC#枚举标志-两种方式绑定-枚举-类-枚举
【发布时间】:2015-07-16 21:18:40
【问题描述】:

我有以下枚举

[Flags]
public enum WeekDays
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

在用户界面中,用户可以选择特定的日子:例如星期一、星期二、星期三。星期一、星期二、星期三的用户选择是 7。此值保存在数据库中名为 Days 的列中。

现在如果我有课:

public class Week
{
    public bool Monday { get; set; }
    public bool Tuesday { get; set; }
    public bool Wednesday { get; set; }
    public bool Thursday { get; set; }
    public bool Friday { get; set; }
    public bool Saturday { get; set; }
    public bool Sunday { get; set; }
}

如何绑定该值 7 并使相应的属性为真或假。示例:7 等价于星期一、星期二、星期三枚举。如果我将值 7 转换为我的类周,结果将是属性:星期一、星期二、星期三为真,其余为假。

如果我有一个班级周,其中属性:星期一、星期二、星期三为真,并将其转换为枚举 WeekDays,结果将为 7。

我该怎么做?

【问题讨论】:

  • 在 db 中只有一个名为 Days 的属性,它是 int 并且包含一个值,比如说 7,它代表距离枚举的 3 天。
  • .NET 4 或更高版本:myenum.HasFlag(MyEnum.Value)
  • term bit masking 可能会引导您找到答案

标签: c# enums enum-flags


【解决方案1】:

最简单的方法之一是使用按位与 (&) 或 Enum.HasFlags() 检查标志。我将两者混合显示:

Week Bind(WeekDays days)
{
    var w = new Week();
    w.Monday = (days & WeekDays.Monday) == WeekDays.Monday;
    w.Tuesday = days.HasFlag(WeekDays.Tuesday);
    w.Wednesday = (days & WeekDays.Wednesday) == WeekDays.Wednesday;
    w.Thursday = days.HasFlag(WeekDays.Thursday);
    w.Friday = (days & WeekDays.Friday) == WeekDays.Friday;
    w.Saturday = days.HasFlag(WeekDays.Saturday);
    w.Sunday = days.HasFlag(WeekDays.Sunday);

    return w;
}

【讨论】:

  • 只是一件小事 - unary 表示一个参数的运算符。 & 是一个 binary 运算符,因为它需要 2 个参数。如果您想区分&&&,请分别使用bitwiselogical。希望这是有道理的。
  • 多哈。天色已晚,& 似乎比&& 还少。 :)
【解决方案2】:

您可以使Week 具有WeekDays 类型的属性或字段,以跟踪哪些标志处于活动状态。然后你所有的布尔属性只检查那个枚举值,并在设置时正确更新它。这允许您这样做:

Week w = new Week();
w.Monday = true;
Console.WriteLine(w.Days); // Monday
w.Tuesday = true;
w.Wednesday = true;
Console.WriteLine(w.Days); // Monday, Tuesday, Wednesday

请看下面的Week 代码,相当冗长(尽管引入了SetDaysFlag 辅助方法):

public class Week
{
    public WeekDays Days
    { get; set; }

    public bool Monday
    {
        get { return (Days & WeekDays.Monday) != 0; }
        set { SetDaysFlag(WeekDays.Monday, value); }
    }

    public bool Tuesday
    {
        get { return (Days & WeekDays.Tuesday) != 0; }
        set { SetDaysFlag(WeekDays.Tuesday, value); }
    }

    public bool Wednesday
    {
        get { return (Days & WeekDays.Wednesday) != 0; }
        set { SetDaysFlag(WeekDays.Wednesday, value); }
    }

    public bool Thursday
    {
        get { return (Days & WeekDays.Thursday) != 0; }
        set { SetDaysFlag(WeekDays.Thursday, value); }
    }

    public bool Friday
    {
        get { return (Days & WeekDays.Friday) != 0; }
        set { SetDaysFlag(WeekDays.Friday, value); }
    }

    public bool Saturday
    {
        get { return (Days & WeekDays.Saturday) != 0; }
        set { SetDaysFlag(WeekDays.Saturday, value); }
    }

    public bool Sunday
    {
        get { return (Days & WeekDays.Sunday) != 0; }
        set { SetDaysFlag(WeekDays.Sunday, value); }
    }

    /// <summary>
    /// Set or unset the flag on the <c>Days</c> property.
    /// </summary>
    /// <param name="flag">The flag to set or unset.</param>
    /// <param name="state">True when the flag should be set, or false when it should be removed.</param>
    private void SetDaysFlag (WeekDays flag, bool state)
    {
        if (state)
            Days |= flag;
        else
            Days &= ~flag;
    }
}

【讨论】:

  • 谢谢!这就是我要找的东西!
  • Enum 的成员HasFlag 是一只真正的狗;如果性能可能是个问题,那么测试(Days &amp; WeekDays.Thursday) != 0 的速度会快一个数量级。如果 C# 支持 enum 作为泛型约束,则等效于 HasFlag 的泛型方法可能会更有效。
  • @poke:调用Days.HasFlag(WeekDays.Friday) 将导致DaysWeekDays.Friday 都转换为System.Enum 类型的引用,这将需要为每个对象创建新的堆对象。然后Enum.HasFlag 方法将需要获取每个对象的类型,检查它们的兼容性,并从每个对象中提取值,然后才能最终进行简单的按位测试。通用方法可以减少单个委托调度的开销。并且将代码编写为按位测试将导致编译器简单地生成一个简单的按位测试。
【解决方案3】:
[Flags]
public enum WeekDays
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

public class Week
{

    public bool Monday { get; set; }
    public bool Tuesday { get; set; }
    public bool Wednesday { get; set; }
    public bool Thursday { get; set; }
    public bool Friday { get; set; }
    public bool Saturday { get; set; }
    public bool Sunday { get; set; }

    public static explicit operator WeekDays(Week week)
    {

        var points = new[]
        {
            week.Monday,
            week.Tuesday,
            week.Wednesday,
            week.Thursday,
            week.Friday,
            week.Saturday,
            week.Sunday
        };

        WeekDays weekDays = 0;

        for (var i = 0; i < points.Length; i++)
        {
            if (points[i])
            {
                weekDays = weekDays | (WeekDays)(1 << i);
            }
        }

        return weekDays;

    }

    public static explicit operator Week(WeekDays weekDays)
    {
        return new Week
        {
            Monday = weekDays.HasFlag(WeekDays.Monday),
            Tuesday = weekDays.HasFlag(WeekDays.Tuesday),
            Wednesday = weekDays.HasFlag(WeekDays.Wednesday),
            Thursday = weekDays.HasFlag(WeekDays.Thursday),
            Friday = weekDays.HasFlag(WeekDays.Friday),
            Saturday = weekDays.HasFlag(WeekDays.Saturday),
            Sunday = weekDays.HasFlag(WeekDays.Sunday)
        };
    }

    public override string ToString()
    {
        return String.Format("{0},{1},{2},{3},{4},{5},{6}", Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多