【问题标题】:Passing enumerated values to functions将枚举值传递给函数
【发布时间】:2012-09-14 16:34:13
【问题描述】:

假设我有一个将整数作为参数的函数。我希望能够使用枚举列表来保持整数值的组织。

例如,我希望能够定义这些(伪代码):

public enum days
{
    monday,
    tuesday,
    etc...
}

public enum months
{
    january,
    february,
    etc...
}

int doSomething(enum x)
{
    return x + 1;
}

然后就可以使用枚举列表中的任何一个来调用函数,如下所示:

int a = doSomething(days.monday);
int y = doSomething(months.february);

这显然不会按原样工作,因为 doSomething 需要仅使用其中一个枚举(即几天或几个月)来定义。我知道几个选项。一种是简单地转换为 int:

int a = doSomething((int)days.monday);
int y = doSomething((int)months.february);

唯一的问题是这个函数在我的代码中的很多地方都被调用了,而且不得不把“(int)”放在所有地方很笨拙(将这些 int 值组合在一起的主要动机之一进入枚举首先是使代码更具可读性)。

另一种选择是完全避免枚举,而是将值捆绑到容器类中,例如:

static class Days
{
    static int x = 0;

    static int monday = x++;
    static int tuesday = x++;
}

同样,这会起作用,但当我要定义很多这些容器类时,这似乎非常麻烦。

答案很可能是没有更简单的方法,我需要成为一个成年人并接受其中一种选择。但我想我会在承诺之前对此进行全面检查。有第三种选择吗?

【问题讨论】:

    标签: c# enums enumerators


    【解决方案1】:

    你的问题是什么?

    public enum Days : short
    {
        Monday = 1,
        Tuesday = 2,
        ...
    }
    
    DoSomething(Days.Monday);
    
    void DoSomething(Days day)
    {
        Days nextDay = day + 1;
    }
    

    另请注意already built-in enum System.DayOfWeek


    我明白了 OP 的观点,但是 C# 还不支持这一点:

    void DoSomething<T>(T e) where T : enum
    {
        T next  = e + 1;
    }
    

    【讨论】:

    • 写给 System.DayOfWeek,我使用的月份和日期值只是示例。在真正的应用程序中,它们与天或时间完全无关。对于您显示的代码,DoSomething() 函数将只能在 Days 枚举上运行。如果我尝试提供不同的枚举,它将失败。
    • @Gadzooks34:我明白你的意思。但不幸的是,C# 还不支持枚举的通用约束。有关说明,请参阅我更新的帖子。
    【解决方案2】:

    System.DateTime 有什么问题吗?

    这将是最实用的类型。

    【讨论】:

    • 我只是将这些值用作示例。在实际应用中,它们实际上与日期/时间无关。
    【解决方案3】:

    如果你真的只想要 int 值,你可以重载你的方法,也许是这样的?

    int dosomething(enum x)
    {return dosomething((int)x)}
    int dosomething(int x)
    {return x+1}
    

    【讨论】:

    • 我试过了,但我认为你不能真正定义这样的函数。定义 doSomething(enum x) 期望传递整个枚举,而不仅仅是它的一个值,这不是我想要的(抱歉,如果我的伪代码不清楚)。
    • 对不起,我试图建议的是每个枚举都有一个重载,例如dosomething(days x) dosomething(months x) 问题是如果你有很多不同的枚举,这可能会变得很大。
    • 是的。问题是函数是在基础库中定义的,然后用户将定义自己的枚举,而无需访问函数的源代码。
    • 您也许可以从这个答案中调整您需要的内容,尽管我不确定性能是否会很好。 stackoverflow.com/a/7628058/1623719
    【解决方案4】:

    是的,你可以这样做

    public enum days : int
    {
        monday,
        tuesday,
        ...
    }
    

    自动星期一变成 0,星期二变成 1,依此类推

    public enum months : int
    {
        january,
        february,
        ...
    }
    

    几个月都一样

    int doSomething(Enum x)
    {
        return (int)x + 1;
    }
    

    并将其称为

    int a = doSomething(days.monday);
    

    或称它为

    int a = doSomething(months.january);
    

    现在 days.monday equals 0 和之后方法 a 变为 1。

    【讨论】:

    • 这看起来不错,但它不起作用。编译器会抱怨 doSomething() 的参数无效,即使枚举是从 int 派生的。
    • 嗯,这又回到了我在示例中的内容。是的,在函数中转换为 int 会起作用,只是比我想要的更笨拙。
    【解决方案5】:

    或者如果您不想更改所有现有的枚举:

        public static int DoSomething(Enum x) 
        {
            int xInt = (int)Convert.ChangeType(x, x.GetTypeCode());
            DoSomething(xInt);
        }
    

    如此处所述:enums-returning-int-value

    【讨论】:

    • 这是一个非常酷的技巧。我认为这会奏效。我唯一担心的是性能(尽管我没有在我的问题中提到这一点)。似乎转换可能很慢:Faster version of Convert.ChangeType
    • 好吧,如果运行时性能更重要,我会建议在泛型线上的东西,在其他地方价格昂贵但性能更好。
    【解决方案6】:
    public enum days : int 
    { monday, tuesday,
    
    }
    
    public enum months :int
    { january, february, march,
    
    }
    
    public  int doSomething(int z)
    {
      return z + 1;
    }
    

    // 你的调用方法 int c = ee.doSomething((int)testenums.months.march); int c = ee.doSomething((int)testenums.day.February);

    工作代码,因为你总是传递 enum 并且是 int 类型,你只需要解析和发送这个代码就可以完美地工作..让我知道

    【讨论】:

    • 我相信如果您将代码复制并粘贴到 ide 中,您会发现它不起作用,而是产生我所描述的问题(函数 doSomething() 参数的类型无效)。
    • 为什么它不起作用..它是一个工作代码你为什么会返回一个无效的参数类型..你只需要查看它。 int c = ee.doSomething((int)testenums.months.march),检查你的枚举类型是短还是int
    【解决方案7】:

    您是否尝试通过参数重载函数:

    int DoSomething(Enum1 value)
    int DoSomething(Enum2 value)
    

    【讨论】:

    • 请看我对 Sconibulus 的回复。
    【解决方案8】:

    我在这上面花了“一点”时间,因为遇到了同样的问题(解决方案)。 所以这是我在 (.NET 4)、Windows 窗体上运行良好的解决方案:

    VB:NET
    
               Private Function DoSomething(Of TEnum As {IComparable, IConvertible, IFormattable})(ByVal valueEnum As TEnum) As Int32
    
                  Dim i As Int32 = CInt(Convert.ChangeType(valueEnum, valueEnum.GetTypeCode()))
                  //Do something with int
                  i += 1
                  Return i
    
               End Function
    
        C#
    
            private int DoSomething<TEnum>(TEnum valueEnum) where TEnum: IComparable, IConvertible, IFormattable 
                        {
                            int i = 0;
                            i = (int)Convert.ChangeType(valueEnum, valueEnum.GetTypeCode());
                            i++;
                            return i;
                        }
    

    【讨论】:

      猜你喜欢
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多