【问题标题】:C# Use int constants vs Enums without castC# 使用 int 常量与没有强制转换的枚举
【发布时间】:2015-07-11 10:44:37
【问题描述】:

我有一些 int 常量分组在几个 Enum 中,例如:

enum myEnum{ 
OBJECT_A = 10, OBJECT_B = 13 };

现在我有几个函数可以使用这个枚举并做一些事情,比如:

void myfunc(myEnum e)
{ .... }

在我的代码中,我需要以这两种方式使用 myfunc:

myfunc(myEnum.OBJECT_A);
myfunc(13);

这会产生错误,因为 int 不会隐式转换为 Enum。

您推荐什么作为最佳做法来保持代码的可读性?

一个明显的解决方案是使用 myfunc((myEnum)13);但这很无聊,因为每次都需要转换 int 并且代码很繁重。

到目前为止,我所做的是(完全避免枚举):

using EChannelInt = System.Int32;

public static class EChannel
{
    public static readonly int CH_CONNECTION        = 10;
    public static readonly int CH_DATA              = 50;
}

public void doit(EChannelInt ch)
{ .... }

doit(EChannel.CH_DATA);
doit(10);

这行得通,但我不太喜欢它,因为它看起来像是一个“技巧”或重命名 thigs。你有什么建议?也许“隐式运算符”可能有用?

【问题讨论】:

  • 规范中的澄清:int 通常不能隐式转换为枚举类型,数字文字 0 除外
  • "在我的代码中,我需要" -- 不,你不需要:很明显可以禁止 myfunc(13) 而不会丢失任何功能:调用者可以写 myfunc((myEnum)13)反而。你想要。那是另一回事。你为什么想要?也许理解你的推理可以让你找到更好的方法。
  • 在代码周围传递13 会降低可读性并使代码更容易出错。尽早将 13 转换为 myEnum.OBJECT_B,并在其余代码中使用 myEnum.OBJECT_B。创建大量重载函数或允许将 int 隐式转换为枚举将创建不易阅读且难以维护的代码。

标签: c# enums


【解决方案1】:

你可以重载myFunc:

void myFunc(int i)
{
    myFunc((myEnum)i);
}

【讨论】:

  • 这就是我为类似案例所做的,并且效果很好。但是,添加了一些验证以确保传递的 int 和 enum 值之间的兼容性。
【解决方案2】:

您可以使用type-safe-enum 模式,并且可以覆盖隐式转换运算符。

public class EChannel
{
    public int Value {get; private set;};

    public static readonly EChannel CH_CONNECTION        = new EChannel(10);
    public static readonly EChannel CH_DATA              = new EChannel(50);

    private EChannel(int value)
    {
        Value = value;
    }

    public static implicit operator EChannel(int a)
    {
        EChannel eChannel = null;
        switch (a) // this need to be changed to something more light
        {
            case 10:
                eChannel = CH_CONNECTION;
                break;
            case 50:
                eChannel = CH_DATA;
                break;
            default:
                throw new Exception("Constant don't exists");
        }
        return eChannel;
    }
}

然后你就这样使用它

public void doit(EChannel ch)
{ .... }

doit(EChannel.CH_DATA);
doit(10);

【讨论】:

    【解决方案3】:

    超载怎么样?

    void myfunc(int i)
    {
        myfunc((myEnum)i);
    }
    

    (如果您无法控制班级,您可以使用extension method。)

    【讨论】:

    • 确实如此,但是由于这些函数很多,我不得不重载它们中的每一个来处理枚举......所以我得到每个函数的两个副本......是吗这种方式可读吗?
    • @edoedoedo 我认为它是可读的,是的。如果你有很多,也许你应该将 all 设为 int 版本的扩展方法,这样它们就可以远离类的主要内容。
    【解决方案4】:

    我会尽可能地坚持枚举值,并且只在绝对必要时(如果有的话)在狭窄的范围内强制转换为 int

    但是,如果您坚持混合整数和枚举值,那么您应该考虑从整数中定义 enum 成员,以保证它们是一致的。

    例子:

    public static class EChannel
    {
        public const int CH_CONNECTION = 10;
    }
    
    public enum myEnum
    {
        CH_CONNECTION = EChannel.CH_CONNECTION
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 1970-01-01
      • 1970-01-01
      • 2021-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多