Enum是对的吗?

时间:2017-06-02 20:21:59

标签: c# enums

我正在使用Model并使用enum获取指定商品列表。

class Verse
{
    public int Number { get; set; }
    public string Text { get; set; }
}
class Chapter
{
    public int Number { get; set; }
    public List<Verse> Verses { get; set; }
}
class Book
{
    public string Name { get; set; }
    public List<Chapter> Chapters { get; set; }
}
class Bible
{
    public Versions Version { get; set; }
    public List<Book> Books { get; set; }
}

enum Versions
{
    asv1901,
    bbe,
    darby,
    kjv,
    nasb,
    niv,
    nkjv,
    nlt,
    rsv,
    web,
    ylt
}

这似乎是一种合乎逻辑的方式,但我发现使用enum会增加不必要的麻烦。

foreach (var chapter in chapters)
{
    var bibleitem = new Bible();
    bibleitem.Version = (Versions)Enum.Parse(typeof(Versions), chapter.version);
}

使用string[]或其他什么更有意义吗?我确信enum还有一些额外的好处,但我对自己的好处提出质疑。

5 个答案:

答案 0 :(得分:7)

微软的指导意见如下:

https://msdn.microsoft.com/en-us/library/ms229058%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396

特别注意:不要对开放集使用枚举

人们一直在写新的圣经,所以你的枚举值可能会改变。最好使用字符串常量,例如,您可以随意添加更多字符串常量。

虽然我们对此有所了解,但仍会对您的代码提出一些额外的批评。

class Verse
{
    public int Number { get; set; }
    public string Text { get; set; }
}

为什么这是一个类,为什么这些属性可以设置?你是否想过拥有现有的诗歌,并希望将它的数量和文字改为不同的东西?如果没有,那就不要允许。我会把它写成

struct Verse
{
    public int Number { get; private set; }
    public string Text { get; private set; }
    public Verse(int number, string text) : this() 
    {
      this.Number = number;
      this.Text = text;
    }
}

创建后,它不会改变。此外,这是一个小的不可变的东西,逻辑上是一个值,所以把它作为一个结构。

class Chapter
{
    public int Number { get; set; }
    public List<Verse> Verses { get; set; }
}

同样,如果你有一个现有章节,你是否打算改变这组经文?因为任何人都可以在列表中调用Add。此外,这会限制您始终使列表可用,而不是懒惰地从数据库计算。制作此IEnumerable<Verse>

enum Versions
{
  asv1901,
  bbe,

这违反了命名准则和一般易读性。把事情拼出来! AmericanStandardVersion1901远远优于asv1901

答案 1 :(得分:1)

当您在代码中有一个命名的常量列表时,您应该使用枚举,并且您知道此特定列表不会随着时间的推移而发生变化(因此称为常量名称列表)。

你得到了什么好处? 可读性。使用枚举可以提高代码的可读性。考虑我有2种员工类型的场景:Permanent和ContractBased。现在我可以在我的代码中执行此操作:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="210mm"
   height="297mm"
   viewBox="0 0 744.09448819 1052.3622047"
   id="svg2"
   version="1.1"
   inkscape:version="0.91 r13725"
   sodipodi:docname="drawing.svg"
   inkscape:export-filename="C:\Users\adili_000\Desktop\drawing.png"
   inkscape:export-xdpi="125"
   inkscape:export-ydpi="125">
  <defs
     id="defs4" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="1.4"
     inkscape:cx="470.51389"
     inkscape:cy="692.09768"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="1920"
     inkscape:window-height="1017"
     inkscape:window-x="-8"
     inkscape:window-y="-8"
     inkscape:window-maximized="1">
    <inkscape:grid
       type="xygrid"
       id="grid4172" />
  </sodipodi:namedview>
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1">
    <rect
       style="opacity:1;fill:#00c8fc;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect4155"
       width="45.714287"
       height="30"
       x="37.387959"
       y="115.30345" />
    <rect
       style="opacity:1;fill:#00c8fc;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect4155-5"
       width="45.714287"
       height="30"
       x="91.899246"
       y="115.40621" />
    <path
       sodipodi:type="star"
       style="opacity:1;fill:#f1c8fc;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="path4841"
       sodipodi:sides="8"
       sodipodi:cx="288.21429"
       sodipodi:cy="396.29076"
       sodipodi:r1="21.58555"
       sodipodi:r2="10.792775"
       sodipodi:arg1="1.0471976"
       sodipodi:arg2="1.4398967"
       inkscape:flatsided="false"
       inkscape:rounded="0"
       inkscape:randomized="0"
       d="m 299.00707,414.98441 -9.38404,-7.9932 -6.99549,10.1496 -0.98347,-12.28755 -12.12341,2.23029 7.99319,-9.38404 -10.1496,-6.99549 12.28756,-0.98347 -2.23029,-12.12341 9.38404,7.99319 6.99549,-10.1496 0.98347,12.28756 12.12341,-2.23029 -7.99319,9.38403 10.14959,6.99549 -12.28755,0.98348 z" />
  </g>
</svg>

此类代码难以阅读和维护,因为没有人能猜出employee.Type == 1或employee.Type == 2的含义。

如果我定义一个enum而不是这样:     枚举EmployeeType {Permanent = 1,ContractBased = 2}

我的代码变成这样:

if employee.Type == 1
    // deal with permanent employee
else if employee.Type == 2
    // deal with contract based employee here

代码的可读性最大化,我也可以使用intellisense。

字符串的问题: 1)您最终会在代码中使用硬编码的字符串文字 2)没有intellisense 3)更多的内存消耗

如何应对增加的复杂性? 你应该为chapter.Version(现在缺少)而不是int有一个枚举类型变量。那样你就不需要进行解析了。

答案 2 :(得分:0)

but I'm finding that working with enum is adding unnecessary difficulty.

这取决于您的需求。如果你的集合不会改变枚举是最好的方法,因为它增加了一个更详细的描述和有限的集合,当你在同一个项目上与许多开发人员一起工作时无法绕过。

但是

如果您的设置在开发解决方案期间可以更改,并且您无法预览该设置而不是字符串将是更好的方法

答案 3 :(得分:0)

在以下情况下,枚举通常效果最佳:

  1. 没有人会很快添加或删除记录(希望永远不会)。
  2. 您不需要使用枚举记录背后的实际价值。
  3. 您不需要使用您的记录名称。
  4. Enum.Parse可以用来从string获取枚举记录,但是你注意到它非常难看,我不鼓励你使用它。如果你有整数枚举值,你可以简单地执行这样的演员:

    Versions version = (Versions)0;
    

    但请注意,枚举不保证属于int类型,它也可以是任何其他整数值。 int恰好是默认值。但是我也不鼓励你依赖于枚举的实际积分值,因为这样的事情也是可能的:

    public enum Versions
    {
       One = 1, 
       Two = 2, 
       Three = 3
    }
    
    public void Do()
    {
       Versions version = (Version)-9;
       // version is now Versions.One.
       // Its value however is -9, what kind of version should -9 be?
    }
    

    上面的代码运行没有错误,因为运行时不会对您用于转换的值执行任何检查。

    您的问题的答案取决于Versions的性质。如果您认为将来不会改变它,那么在大多数情况下,它对于枚举来说是一个很好的假设。但是你应该在整个应用程序中使用枚举。我在您的示例中看到您将该版本用作string,因此需要执行丑陋的Enum.Parse。使用枚举时,一致性是一个重要的因素,但它总是如此,但再次指出它并不会有什么坏处。

    如果您认为自己的记录更具动态性,那么您可能最适合使用string。在这种情况下,您应该始终使用string s。 (只想再次指出)

答案 4 :(得分:0)

使用enum提供了比较此类实例的方法,将实例的值转换为其字符串表示形式,将数字的字符串表示形式转换为此类的实例,并创建指定枚举和值的实例

使用im class更正。

浓淡

public enum Versions 
{        
    asv1901,
    bbe,
    darby,
    kjv,
    nasb,
    niv,
    nkjv,
    nlt,
    rsv,
    web,
    ylt
}

接下来,实施

foreach (var chapter in chapters)
{
     var bibleitem = new Bible();
     bibleitem.Version = (Versions) "Your class enum"(typeof(Versions), chapter.version);
}

Enum和更多用于良好的编程习惯,干净的代码

使用枚举的引用:Enum Class Microsoft