两个成员枚举与布尔值

Ric*_*ter 9 .net enums boolean

这个问题在我的脑海里已经有一段时间了,对不起,如果它看起来是主观的.在公共属性中使用bool和在数据对象中使用构造函数存在一些缺点.请考虑以下代码作为示例.

使用bool:

public class Room
{
    public string Name { get; set; }
    public bool Bookable { get; set; }

    public Room(string name, bool bookable);
}
Run Code Online (Sandbox Code Playgroud)

以及这门课程的使用

Room r = new Room ("101", true);
Run Code Online (Sandbox Code Playgroud)

这是适当的功能,但有另一种方法来实现它:

使用枚举:

public enum BookingStatus
{
    Bookable,
    NotBookable
}

public class Room
{
    public string Name { get; set; }
    public BookingStatus Bookable { get; set; }

    public Room(string name, BookingStatus bookable);
}
Run Code Online (Sandbox Code Playgroud)

以及这门课程的使用

Room r = new Room ("101", BookingStatus.Bookable);
Run Code Online (Sandbox Code Playgroud)

对我来说,这两个看起来功能相同,但每个都有一些优点和缺点:

  • 设置属性时,Enum方法更详细(您可以仅从代码中推断枚举的用法)
  • 可以扩展枚举以支持更多状态(对API特别有用)
  • 枚举需要更多的输入(虽然大大减少了)
  • 枚举不能在条件中使用(即if(r.bookable)),尽管我理解这是微不足道的.

我错过了什么,完全不合适吗?我不知道为什么这会让我这么烦恼,也许我对自己的好处太强迫了!

mau*_*ris 9

仅仅因为可读性和对代码的理解,我将使用枚举而不是布尔值.

比较BookingStatus.Bookabletrue,当然你想了解更多的阅读BookingStatus.Bookable.

也像fforw所提到的那样,如果将来你可能需要添加更多选项,枚举会更容易改变.


ffo*_*orw 5

是否有可能在未来可能有超过最初的两个选项,为枚举添加第三个选项是更少的工作然后将所有bool更改为枚举.


Dav*_*eau 5

对于财产我可能会同意。不过,在“干净代码”中,(正确地)表明 sbool在用作参数时隐藏意图。例如,格式化方法可能如下所示:

public void Format(
   bool bold,
   bool italic,
   bool underline
) {
   ...
}
Run Code Online (Sandbox Code Playgroud)

调用时看起来像:

Format(true, false, true);
Run Code Online (Sandbox Code Playgroud)

相反,它会更具可读性:

public enum Bold { Yes, No }
public enum Italic { Yes, No }
public enum Underline { Yes, No }

public void Format(
   Bold bold,
   Italic italic,
   Underline underline
) {
   ...
}
Run Code Online (Sandbox Code Playgroud)

这使得调用看起来像:

Format(Bold.Yes, Italic.No, Underline.Yes);
Run Code Online (Sandbox Code Playgroud)

(请记住,这只是 bool 参数如何隐藏意图的示例;可能有更好的方法来实现上述代码。)

在您的特定情况下,请注意两个构造函数调用之间的区别:

// enum; intent is clear
Room r = new Room ("101", BookingStatus.Bookable);

// bool; true what?
Room r = new Room("101", true);
Run Code Online (Sandbox Code Playgroud)

这也可以通过使用参数名称来改进:

Room r = new Room("101", bookable: true);
Run Code Online (Sandbox Code Playgroud)

  • 此外,在使用枚举时,不能将包含可能的粗体值的变量放入“斜体”参数槽中。:) 类型安全。 (3认同)

Mar*_*ann 2

Martin Fowler在他的《重构》一书中解释了为什么他认为枚举是一种代码味道,我只能同意。在您的示例中,更好的方法是创建一个抽象 Room 类:

public abstract class Room
{
     public string Name { get; set; }

     public abstract bool Bookable { get; }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以创建派生的 BookableRoom 和 NonBookableRoom 类。

public class BookableRoom : Room
{
    public override bool Bookable
    {
        get { return true; }
    }
}

public class NonBookableRoom : Room
{
    public override bool Bookable
    {
        get { return false; }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么你说这是一个更好的方法?对我来说,这看起来就像复杂性的增加一样。我认为 KISS 原则在这里是合适的。 (15认同)
  • 我同意@nightcoder 的观点,并且对这个答案的选择感到困惑。OP 是否担心枚举不会是一种复杂且冗长的“足够”翻转单个位的方法?那么我们应该将每个对象类型的每个运行时状态烘焙到我们的源代码中吗?马丁·福勒(Martin Fowler)究竟说了什么来捍卫这种做法? (6认同)
  • 那么当你拥有多个状态属性时该怎么办呢?添加更多课程?添加提供每种可能的状态组合的类? (2认同)