C# 中是否有模式或方法来检查 (int 1,2,4,8,...) 选项是 true 还是 false

发布于 2024-11-08 19:11:11 字数 902 浏览 0 评论 0原文

我喜欢编写枚举或整数来将选项传递给我的方法。 C# 中是否有模式或方法来检查 (int 1,2,4,8,...) 选项是 true 还是 false。我认为通过二进制函数应该可以轻松实现。

class Program
{
    public enum Option
    {
        Option_A = 1,
        Option_B = 2,
        Option_C = 4,
        Option_D = 8,
    }

    static void Main(string[] args)
    {
        int activeOption = 5; // Means I activeted the Option_A and Option_C
        if (IsOption(activeOption, Option.Option_A)) { /*do work*/ }
        if (IsOption(activeOption, Option.Option_B)) { /*do work*/ }
        if (IsOption(activeOption, Option.Option_C)) { /*do work*/ }
        if (IsOption(activeOption, Option.Option_D)) { /*do work*/ }
    }

    private static bool IsOption(int activeOption, Option option)
    {
        /*Evaluate if IsOption is true or false*/
        throw new NotImplementedException();
    }
}

编辑

我是否限制了我可以像这样创建的选项数量?

I like to write enum or integer to pass option to my methods. Is there a pattern or a method in C# to check if an (int 1,2,4,8,...) option is true or false. I think it should easily be possible via binary functions.

class Program
{
    public enum Option
    {
        Option_A = 1,
        Option_B = 2,
        Option_C = 4,
        Option_D = 8,
    }

    static void Main(string[] args)
    {
        int activeOption = 5; // Means I activeted the Option_A and Option_C
        if (IsOption(activeOption, Option.Option_A)) { /*do work*/ }
        if (IsOption(activeOption, Option.Option_B)) { /*do work*/ }
        if (IsOption(activeOption, Option.Option_C)) { /*do work*/ }
        if (IsOption(activeOption, Option.Option_D)) { /*do work*/ }
    }

    private static bool IsOption(int activeOption, Option option)
    {
        /*Evaluate if IsOption is true or false*/
        throw new NotImplementedException();
    }
}

EDIT

Am I limited the number of options that I can create like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

吻泪 2024-11-15 19:11:11

由于您的枚举包含标志(或者如果您愿意,是一个位字段),因此您应该添加 FlagsAttribute 到它:

[Flags]
public enum Option
{
    Option_A = 1,
    Option_B = 2,
    Option_C = 4,
    Option_D = 8,
}

然后,检查通常使用按位与运算符完成。还需要进行强制转换,因为您使用的是 int 变量。

if(((Option)activeOption & Option.Option_A) != Option.Option_A) //...

如果您想封装这种肮脏的内容,请查看 Smudge202 的答案。如果您运行的是 .NET 4,您甚至不需要这样做:检查 sehe的答案

但您确实应该尝试直接使用 Option 类型的变量,并将选项与按位或运算符组合:

Option activeOption = Option.Option_A | Option.Option_C;

当然,使用此方案会限制您可以创建的选项数量。如果保持原样,则只能创建 32 个不同的选项,因为 int(枚举的默认基础类型)只有 32 位。如果您使用long,您可以有 64 个不同的选项:

[Flags]
public enum Option : long
{
    Option_A = 1,
    Option_B = 2,
    Option_C = 4,
    Option_D = 8,
    // blah blah
}

但是,如果您需要任意数量的选项,则可能是时候改变策略了。您可以创建一个行为类似于枚举的自定义类型,但是使用常规的非标志枚举和 HashSet

public enum Option
{
    Option_A = 1, // notice the sequential values now
    Option_B = 2,
    Option_C = 3,
    Option_D = 4,
}

HashSet<Option> options = new HashSet<Option> { Option.Option_A, Option.Option_C };
if(options.Contains(Option.Option_A)) // ...

Since your enum contains flags (or if you prefer, is a bitfield), you should add a FlagsAttribute to it:

[Flags]
public enum Option
{
    Option_A = 1,
    Option_B = 2,
    Option_C = 4,
    Option_D = 8,
}

And then, checking is typically done with the bitwise and operator. A cast will also be needed, because you are using an int variable.

if(((Option)activeOption & Option.Option_A) != Option.Option_A) //...

If you want to encapsulate this nastiness away, check out the article linked in Smudge202's answer. If you are running .NET 4, you don't even need to do that: check sehe's answer.

But you should really try using a variable of type Option directly, and combine the options with the bitwise or operator:

Option activeOption = Option.Option_A | Option.Option_C;

Of course using this scheme limits the number of options you can create. If you leave it as is, you can only create 32 different options, because an int (the default underlying type of an enum) has only 32-bits. If you use a long you can have 64 different options:

[Flags]
public enum Option : long
{
    Option_A = 1,
    Option_B = 2,
    Option_C = 4,
    Option_D = 8,
    // blah blah
}

However, if you need an arbitrary number of options, it's probably time to change strategies. You could make a custom type that behaves like an enum, but you'll probably be better off with just a regular, non-flags enum, and a HashSet<Option>.

public enum Option
{
    Option_A = 1, // notice the sequential values now
    Option_B = 2,
    Option_C = 3,
    Option_D = 4,
}

HashSet<Option> options = new HashSet<Option> { Option.Option_A, Option.Option_C };
if(options.Contains(Option.Option_A)) // ...
嘴硬脾气大 2024-11-15 19:11:11

使用按位 AND 检查 option 中的位是否在 activeOption 中设置。您还需要使两个参数的类型相同,以便运算符能够工作(无论如何,您都在检查 Option 位掩码中的位):

private static bool IsOption(Option activeOption, Option option)
{
    return (activeOption & option) == option;
}

Use bitwise AND to check if the bits in option are set in activeOption. You also need to make both parameters the same type so the operator will work (you are checking the bits in an Option bitmask anyway):

private static bool IsOption(Option activeOption, Option option)
{
    return (activeOption & option) == option;
}
深海里的那抹蓝 2024-11-15 19:11:11

除了提到的 FlagsAttribute 之外,在 C# 中还有 Enum.HasFlag 方法

using System;

[Flags] public enum DinnerItems {
   None = 0,
   Entree = 1,
   Appetizer = 2,
   Side = 4,
   Dessert = 8,
   Beverage = 16, 
   BarBeverage = 32
}

public class Example
{
   public static void Main()
   {
      DinnerItems myOrder = DinnerItems.Appetizer | DinnerItems.Entree |
                            DinnerItems.Beverage | DinnerItems.Dessert;
      DinnerItems flagValue = DinnerItems.Entree | DinnerItems.Beverage;
      Console.WriteLine("{0} includes {1}: {2}", 
                        myOrder, flagValue, myOrder.HasFlag(flagValue));
   }
}
// The example displays the following output:
//    Entree, Appetizer, Dessert, Beverage includes Entree, Beverage: True

In addition to FlagsAttribute mentioned, in C# there is the Enum.HasFlag Method

using System;

[Flags] public enum DinnerItems {
   None = 0,
   Entree = 1,
   Appetizer = 2,
   Side = 4,
   Dessert = 8,
   Beverage = 16, 
   BarBeverage = 32
}

public class Example
{
   public static void Main()
   {
      DinnerItems myOrder = DinnerItems.Appetizer | DinnerItems.Entree |
                            DinnerItems.Beverage | DinnerItems.Dessert;
      DinnerItems flagValue = DinnerItems.Entree | DinnerItems.Beverage;
      Console.WriteLine("{0} includes {1}: {2}", 
                        myOrder, flagValue, myOrder.HasFlag(flagValue));
   }
}
// The example displays the following output:
//    Entree, Appetizer, Dessert, Beverage includes Entree, Beverage: True
烛影斜 2024-11-15 19:11:11

如果您使用的是 .NET 4.0,则可以使用 HasFlag

static void Main(string[] args)
{
    Option activeOption = (Option)5; // Means I activeted the Option_A and Option_C
    if (activeOption.HasFlag(Option.Option_A)) { /*do work*/ }
    if (activeOption.HasFlag(Option.Option_B)) { /*do work*/ }
    if (activeOption.HasFlag(Option.Option_C)) { /*do work*/ }
    if (activeOption.HasFlag(Option.Option_D)) { /*do work*/ }
}

If you are using .NET 4.0 you can use HasFlag.

static void Main(string[] args)
{
    Option activeOption = (Option)5; // Means I activeted the Option_A and Option_C
    if (activeOption.HasFlag(Option.Option_A)) { /*do work*/ }
    if (activeOption.HasFlag(Option.Option_B)) { /*do work*/ }
    if (activeOption.HasFlag(Option.Option_C)) { /*do work*/ }
    if (activeOption.HasFlag(Option.Option_D)) { /*do work*/ }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文