当前位置 : 主页 > 编程语言 > c语言 >

如何处理C#中的枚举0(CA1008讨论)

来源:互联网 收集:自由互联 发布时间:2021-06-25
规则 CA1008指定所有枚举都应该具有应该命名为Unknown的0值(我们不在此讨论标志).我理解你想要防止未初始化的值自动获得意义的原因.假设我定义了以下枚举: enum Gender{ Male, Female}class
规则 CA1008指定所有枚举都应该具有应该命名为Unknown的0值(我们不在此讨论标志).我理解你想要防止未初始化的值自动获得意义的原因.假设我定义了以下枚举:

enum Gender
{
    Male,
    Female
}

class Person
{
    public string Name { get; set; } 
    public Gender Gender { get; set; }
}

这规定每个人应该是男性或女性(暂时不要讨论性别讨论).如果我忘记设置Gender属性,那么此人自动为男性,这可能会导致问题.因此,我了解CA1008警告,因此应为未知/未初始化的值保留0值.

因此,让我们将性别枚举更改为不再使用0值:

enum Gender
{
    Male = 1,
    Female = 2
}

当我没有指定性别时,那个人不是男性或女性.序列化期间可能会出现问题.对于调试期间的枚举,值0不是非常具有描述性.要修复它并避免CA1008警告,我再次更改枚举:

enum Gender
{
    Unknown = 0,
    Male = 1,
    Female = 2
}

未初始化的属性现在显示为Unknown,看起来不错.但我可能已经介绍了另一个问题,那就是Unknown值看起来像一个有效的值,可以应用于用户.我也可能会收到有关不处理所有枚举值的警告.假设,我使用构造函数,要求我指定性别和名称以避免未初始化的属性:

public Person(string name, Gender gender)
{
     Name = name ?? throw new ArgumentNullException(name);
     Gender = gender;
}

当我定义未知枚举时,我现在可以明确地将性别设置为未知.当然,这可以在构造函数中检查,但这只会在运行时发出信号.如果未定义未知值,则调用者只能将其设置为男性或女性.

修复可能是使用可空的性别属性,因此未初始化的值是显式空值(我们不再定义未知值).但是使用可空类型会使编程变得更复杂,所以我不建议它.

将ObsoleteAttribute应用于Unknown值可能是个好主意.当某人明确使用该值时,它会被标记为警告(在构建时).

处理未初始化的枚举值的正确方法是什么,并且使用ObsoleteAttribute是一个好主意还是有其他缺点?

笔记:
*虽然过时不是这里的正确语义,但如果使用该值,它是唯一(简单)生成警告的方法.
*在没有默认构造函数的情况下使用POCO可能会使序列化变得复杂,因此在没有它们的情况下拥有(可序列化的)类通常是个坏主意.

is using the ObsoleteAttribute a good idea?

不.使用[已废弃]等待…将过时的成员标记为已废弃.这是[已废弃]的唯一正确用法.不要为现有的词语发明新的含义;这只会造成混乱.

What is the proper way to deal with the uninitialized enumeration values?

这是错误的问题.退后一步.让我们看一下你问题的大图:

>你决定使用枚举
>你有一堆警告说你的枚举违反了一些指导原则,你认为指南很重要
>您按照指南进行的每一次尝试都会产生一个新问题,您认为这些问题很重要.

现在你被卡住了,想知道该怎么做.

你要做的是:回到第一步到第三步,做出不同的决定.

假设我们重新审视决策3.您已经确定了每个解决方案的一些优缺点.决定对于其中一个,优点超过缺点,并与它一起去.

假设我们重新审视了决策2.你违反了一系列指导方针.准则不是规则.您可以确定指南对您的方案是不好的建议,记录您故意违反它们的原因以及为什么,禁止警告,然后前进.

假设我们重新审视决定1.你是那个决定将性别最好地表现为枚举的人,而且看起来这个决定已经给你带来了相当大的痛苦.所以拒绝这个决定:

abstract class Gender : 
   whatever interfaces you need for serialization and so on
{
  private Gender() { } // prevent subclassing 
  private class MaleGender : Gender 
  {
    // Serialization code for male gender
  }
  public static readonly Gender Male = new MaleGender();
  // now do it all again for FemaleGender
}

我们得到了什么?我们有Gender.Male和Gender.Female与之前相同,它们可以像以前一样序列化,并且Gender类型的任何值都是男性,女性或null.不喜欢nulls?抛出一个异常,就像你为这个人的名字得到一个空字符串一样.想要添加更多性别,例如“Unknown”或“Nonbinary”或其他什么?添加新的子类型和静态字段.

你没有被迫使用枚举.如果满足枚举的准则让您烦恼,请停止使用枚举.

网友评论