枚举类型最好放在哪里?

45

我发现通常有一个单一类型或命名空间可以将任何特定的枚举作为参数传入,因此我总是在那里定义这些枚举。然而,最近我的一位同事对此提出了很大的质疑,认为这样做是愚蠢的,应该始终在项目根目录下定义枚举类型的枚举命名空间。

最佳的枚举类型存放位置是什么?


2
任何与“最佳实践”相关的事情都是主观的,但我认为你的同事是错的。.NET框架不包括一个Enums命名空间,这是有充分理由的。将枚举放在它们最合适的命名空间中(如果适用的话,可以将它们嵌套在类中)。 - John Rudy
7
在你的同事解释他/她的问题之前,“愚蠢”并不是你可以采取行动的有效指标。 - DK.
这样说来,同事是错误的。如果解决方案有许多项目,并且枚举在多个项目中使用,则将它们放在一个地方是有意义的。 - Bakudan
10个回答

49

为什么要将枚举类型与其他类型区分开来?将它们保留在相同的命名空间中,因为它们很可能被其他类使用 - 并且假设它们将被其他类使用,则将它们作为自己文件中的顶级类型。

我唯一经常将类型“clump”在一起的类型是委托 - 有时我会在Delegates.cs文件中放置一堆委托。 不过,随着 .NET 3.5 和 Func / Action 的出现,情况变得不那么常见了。


9
此外,命名空间是为了将逻辑上属于一起的东西分离开来。并非所有类都应该放在同一个命名空间中,仅仅因为他们是类。同样地,不是所有的枚举类型都应该放在同一个命名空间,仅仅因为它们是枚举类型。将它们与它们逻辑上属于的代码放在一起。

5
我认为枚举和常量应该放在最多使用它们来控制代码决策的类中,并使用代码自动完成来查找它们。这样你就不必记住它们在哪里,它们与类相关联。例如,如果我有一个ColoredBox类,那么我就不必考虑它们在哪里。它们将成为ColoredBox的一部分。ColoredBox.Colors.Red,ColoredBox.Colors.Blue等。 我把枚举和常量看作是该类的属性或描述。 如果它被多个类使用,而没有一个类占主导地位,那么拥有一个枚举类或常量类是合适的。 这遵循了封装的规则。将属性从不同的类中隔离出来。如果您决定更改Circle对象中红色的RGB,但不想更改ColoredBox对象中的红色,则封装其属性可以实现这一点。

5

一般来说,我会将所有不同类型(类、接口和枚举)放在它们自己的文件中,无论它们有多小。这样做可以更容易地找到和管理它们所在的文件,尤其是当您不在Visual Studio中并且没有“转到定义”功能时。我发现几乎每次我将一个像那样“简单”的类型放在另一个类中时,我最终要么在以后添加内容,要么以一种不再合理的方式重用它,这时它就需要拥有自己的文件。

至于使用哪个命名空间,这取决于您正在开发的任何内容的设计。通常,我尝试模仿.NET框架的约定。


5

我尝试将与类相关的所有内容都放在类中,这不仅包括枚举,还包括常量。我不想去其他地方搜索包含枚举的文件或类。在一个有很多类和文件夹的大型应用程序中,很难确定在哪里放置枚举文件以便于查找。

如果枚举在几个紧密相关的类中使用,您可以创建一个基类,以便共享诸如枚举之类的常见类型。

当然,如果枚举真的很通用并且被广泛使用,您可能需要为它们创建一个单独的类,以及其他通用实用程序。


3
如果我打算在类之外使用我的枚举,我会为该枚举创建一个单独的源文件。否则,我将把它放在我想要使用它的类内部。请注意保留HTML标签。

3
我会使用嵌套命名空间来实现此功能。我更喜欢它们,因为在类中放置枚举类型,即使 MyEnum 不会与其他作用域内的任何东西发生冲突,在类外部你仍然必须使用完整的 MyClass::MyEnum 语法。
通过使用嵌套命名空间,您可以使用 "using" 语法。此外,我将把与特定子系统相关的枚举类型放在自己的文件中,这样就不会出现必须包含整个世界才能使用它们的依赖问题。
因此,在枚举头文件中,您会得到:
// MyEnumHeader.h
// Consolidated enum header file for this dll,lib,subsystem whatever.
namespace MyApp
{
  namespace MyEnums
  {
    enum SomeEnum { EnumVal0, EnumVal1, EnumVal2 };
  };
};

然后在类头文件中,您会得到:

// MyInterfaceHeader.h
// Class interfaces for the subsystem with all the expected dependencies.

#include "MyEnumHeader.h"

namespace MyApp
{
  class MyInterface
  {
  public:
    virtual void DoSomethingWithEnumParam (MyEnums::SomeEnum enumParam) = 0;
  };
};

可以根据实际情况使用多个枚举头文件。我喜欢将它们与类头文件分开,这样在系统其他地方使用枚举变量时就不需要类头文件。如果枚举在类内部声明,那么在其他地方使用时就必须要有封装类定义。

并且如前所述,在外部代码中您可以使用以下内容:

using namespace MyApp::MyEnums;

2

什么环境?

在.NET中,我通常创建一个空的类文件,将其重命名为MyEnum或其他名称以表示它保存了我的枚举,并在其中声明它。


.NET,但我认为在 C++ 中也是一样的。 - aceinthehole

2
通常我发现枚举类型围绕一个单独的类中心 -- 就像 MyClassOptions 一样。
在这种情况下,我将枚举放在与 MyClass 相同的文件中,但在命名空间内部但在类外部。
namespace mynamespace
{
  public partial class MyClass
  {
  }
  enum MyClassOptions
  {
  }
}

1

我倾向于在使用明显的情况下定义它们。如果我有一个typedef用于某种原因的结构体...

typedef enum {
  HI,
  GOODBYE
} msg_type;

typdef struct {
 msg_type type;
 union {
   int hivar;
   float goodbyevar;
  }
} msg;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接