【问题标题】:Extension method for adding value to bit field (flags enum)位域加值的扩展方法(标志枚举)
【发布时间】:2011-08-13 04:54:28
【问题描述】:

而不是这样做来为 flags 枚举变量添加一个值:

MyFlags flags = MyFlags.Pepsi;
flags = flags | MyFlags.Coke;

我想创建一个扩展方法来实现这一点:

MyFlags flags = MyFlags.Pepsi;
flags.Add(MyFlags.Coke);

可能吗?你是怎么做到的?

【问题讨论】:

    标签: c# .net enums flags bit-fields


    【解决方案1】:

    没有任何用处。枚举是值类型,因此在创建扩展方法时,会传入枚举的副本。这意味着您需要返回它才能使用它

        public static class FlagExtensions
        {
            public static MyFlags Add(this MyFlags me, MyFlags toAdd)
            {
                 return me | toAdd;
            }
        }
    
        flags = flags.Add(MyFlags.Coke); // not gaining much here
    

    另一个问题是你不能以任何有意义的方式使这个通用化。您必须为每个枚举类型创建一个扩展方法。

    编辑:

    您可以通过颠倒枚举的角色来得出一个不错的近似值:

    public static class FlagsExtensions
    {
        public static void AddTo(this MyFlags add, ref MyFlags addTo)
        {
             addTo = addTo | add;
        }
    }
    
    
    MyFlags.Coke.AddTo(ref flags);
    

    【讨论】:

    • 我不能让第一个参数通过引用传递?
    • 不在扩展方法中。您可以创建一个标准的实用程序方法并这样做。您可能可以翻转方法,将添加的方法设为this 参数,将接收方设为 ref 参数。 MyFlags.Coke.AddTo(flags);
    • 为什么不能在扩展方法中做呢?
    • 这就是 C# 霸主们决定的 :) 我敢肯定有很好的技术原因为什么不这样做。
    • Necro'ing 好像这个添加可以通过addTo |= add来简化。
    【解决方案2】:

    我也在研究Enum 扩展方法。

    我尝试为Enums 创建添加/删除通用方法,但我发现它是多余的。

    添加你可以这样做:

    MyFlags flags = MyFlags.Pepsi;
    flags |= MyFlags.Coke;
    

    要删除你可以这样做:

    MyFlags flags = MyFlags.Pepsi | MyFlags.Coke;
    flags &= ~MyFlags.Coke;
    

    不要使用异或(^),如果不存在则添加标志。

    flags ^= MyFlags.Coke; // Do not use!!!
    

    希望它有所帮助。更多扩展方法见:My blog

    【讨论】:

    • XOR 实际上切换了标志——就像你说的,如果它不存在,它会添加它,但如果它确实存在,它也应该删除它。 A good reference(虽然是指Javascript)
    【解决方案3】:

    不是解决方案,但如果您的目标是减少冗长并提高可读性,那么带有扩展方法的流畅接口至少可以部分提供帮助:

    [Flags]
    public enum MyFlags
    {
        None = 0,
        A    = 0x1,
        B    = 0x2,
    }
    
    public static class MyFlagsExt
    {
        public static MyFlags A(this MyFlags myFlags)
        {
            return myFlags | MyFlags.A;
        }
    
        public static MyFlags B(this MyFlags myFlags)
        {
            return myFlags | MyFlags.B;
        }
    }
    
    ...
    
    var flags = MyFlags.A.B();
    

    【讨论】:

    • 减少冗长不应该是任何人在 C# 中的目标。它被编译为符号,因此代码的文件大小无关紧要。更详细~= 更易读。同样,MyFlags.A.B() 对我来说毫无意义。为了让我理解这段代码,我必须理解程序员(你)和你的思维方式。这不利于可读性或可维护性。此外,此答案中的任何内容都不是界面。所以这里没有流畅的界面,无论是合同还是 UI。我只能同意你回答的前三个字。
    • 没有理由根据个人喜好投反对票,只看答案是否符合问题。详细程度与文件大小无关。有经验的程序员知道过于冗长的代码更难理解,因为它会降低信噪比。如果 OP 希望在这种情况下减少冗长,我相信他或她的判断。另见此处:softwareengineering.stackexchange.com/questions/141175/…
    • 1. OP 从未说过他们想减少冗长。 2. 我所说的一切都不是个人喜好。 3. 你发布的那个链接不支持你的论点,因为它说你的答案太神秘了。 4. 我还要指出,我的评论说“更详细”关于等于更具可读性。例如:在冗长的名字和神秘的名字之间划清界限,就像你发布的链接提到的那样。 animal.Cat() 将 Cat 标志添加到 Animal 中并不明显。它如何删除 cat 标志?此外,您的单字母示例令人困惑types.P().O().K().E().M().O().N()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多