使用枚举作为可选参数

24

我正在开发的应用程序中有几种使用了可选参数的方法,其中一些是枚举类型。目前,为了实现这一点,我编写了具有相似签名类型的方法:

public void SomeMethod(string myFirstParam = "", string mySecondParam = "", MyEnum myThirdParam = (MyEnum )(-1)){

     if (myThirdParam != (MyEnum ) (-1))
     {
          //do something with it
     }
}

所以我的第一个问题是,这种方法是否存在我没有意识到但最终会痛苦地意识到的一些缺陷? 第二个问题是,是否有更合适或至少更优雅的解决方案?

我应该说,我们控制这种方法的输入,它在内部使用,所以我不担心有人投入一个值为-1来干扰工作。


为什么不给你的MyEnum添加一个额外的值,比如'MyEnum.DEFAULT'呢?这样你就不需要强制转换-1了。 - Soony
我同意。比起创建一个可为空的参数,并且到处都要使用 .HasValue 或者 .Value,只需给枚举类型添加一个 "UNKNOWN" 值会更好。 - djcrabhat
3个回答

29

我建议在这种情况下使用可空枚举(nullable enum),代码如下:

public void SomeMethod(string myFirstParam = "", 
                       string mySecondParam = "", 
                       MyEnum? myThirdParam = null)
{
   if (myThirdParam.HasValue)
   {
      var enumValue = myThirdParam.Value;
      //do something with it
   }
}

你可以像这样使用它:

SomeMethod(myThirdParam: MyEnum.Something);

1
@JonathonReinhart - 你有什么替代建议吗? - El Kabong
@JonathonReinhart:也许我对可空类型的工作细节有所误解,但我不认为_boxing_与此有任何关系。编辑:然而,在这种情况下,我反对使用可空类型,因为它更像是一个_魔法值_。 - Chris Sinclair

21

确保您的enum有一个默认值(等于零),即“无”或“无效”。这将是可选参数的适当默认值。

微软代码分析也推荐这样做,参见CA1008:枚举应该具有零值

例如:

enum SpeakerType
{
    None = 0,
    Woofer,
    Midrange
    Tweeter
}

这种方式中,default 关键字提供了一个合理的值,但不会无意中引用您不想要的内容。


例如,BCL使用相同的概念。要为SerialPort定义使用的停止位数,可以使用StopBits枚举:

public enum StopBits
{
  None,
  One,
  Two,
  OnePointFive,
}

然而,None值是无效的。实际上,

当您将StopBits属性设置为None时,SerialPort类会抛出一个ArgumentOutOfRangeException异常。


我知道其他人建议只使用默认值,但这是最彻底和有力的答案,所以我将接受这个答案,谢谢大家的帮助。 - El Kabong
如果您正在使用某个库中的枚举并希望将默认值设置为枚举中的其他值,则此答案无法提供帮助。我想除非您自己创建一个类似库中枚举的枚举,否则没有其他方法可以实现。 - AndrewBenjamin
使用此解决方案,您可以编写 SomeMethod(string myFirstParam = "", string mySecondParam = "", MyEnum myThirdParam = default(MyEnum)){ if (myThirdParam != MyEnum.None){ /*do something with it */} } - mems

0

关于什么:

enum MyEnum {
   MISSING = -1,
   FirstValue,
   SecondValue,
   ...
}

public void SomeMethod(string myFirstParam = "", string mySecondParam = "", MyEnum myThirdParam = MISSING) {
     if (myThirdParam != MISSING)
     {
          //do something with it
     }
} 

我的答案比这个更好的原因是,这种类型的变量默认为FirstValue,而不是您可能打算的MISSING - Jonathon Reinhart

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