简体   繁体   English

在C#中使用通用方法中的枚举

[英]Using enums in generic methods in C#

I just started learning C# today, and I am trying to make a generic method which can operate on different enums. 我今天刚开始学习C#,我正在尝试制作一个可以在不同枚举上运行的通用方法。 I got some code that I found in another question on paper, but the compiler keeps complaining. 我在纸上的另一个问题中找到了一些代码,但编译器一直在抱怨。 I was wondering if someone could give me a hand. 我想知道是否有人可以帮助我。 Here is what I have so far: 这是我到目前为止:

    static void ReadMenuInput<T>(out T menuInput)
    {
        while (true)
        {
            if (enum<T>.TryParse(Console.ReadLine(), out menuInput) && menuInput < sizeof(T))
            {
                break;
            }
            Console.WriteLine("Please enter a valid input.");
        } 
    }

Thank you for your help! 谢谢您的帮助!

There are a couple of different issues with that particular code snippet, some of them easier to deal with than others. 该特定代码段有几个不同的问题,其中一些比其他代码更容易处理。 A few of them are simply showing your lack of experience: 其中一些只是表明你缺乏经验:

  • enum and Enum are not interchangable; enumEnum不可互换; one is a class name and one is a C# keyword. 一个是类名,一个是C#关键字。 In some cases (say, string and String ) the keyword is just an alias for the type, but enum is not a type name, it is used to define type names. 在某些情况下(例如, stringString ),关键字只是该类型的别名,但enum不是类型名称,它用于定义类型名称。 To call class methods you need to use Enum . 要调用类方法,您需要使用Enum
  • You are trying to call the generic TryParse<> method with the wrong syntax; 您试图使用错误的语法调用通用TryParse<>方法; it should be Enum.TryParse<T> . 它应该是Enum.TryParse<T>
  • Enumerations and integers are not the same type, and you cannot just compare them. 枚举和整数不是同一类型,您不能只比较它们。 They are, however, convertible to one another via an explicit typecast. 但他们却是,通过显式类型转换可转换到另一个。 Since sizeof returns an int , you need such a typecast (but see below). 由于sizeof返回一个int ,你需要这样的类型转换(但见下文)。

The more complex issues with your code sample: 代码示例中更复杂的问题:

  • sizeof(enum) doesn't do quite what you expect, I think; 我认为, sizeof(enum)没有达到预期的效果; it returns the size in bytes of the enum, which is typically going to be 4. You probably want the IsDefined method, which lets you know if a particular integer value is defined in an enumerated type 它返回枚举的大小( 以字节单位) ,通常为4.您可能需要IsDefined方法,它可以让您知道枚举类型中是否定义了特定的整数值
  • As the compiler will tell you, you can only use generic types in this context that are non-nullable. 正如编译器将告诉您的那样,您只能在此上下文中使用不可为空的泛型类型。 The way to define this is with a where T: struct constraint on your generic type. 定义它的方法是在泛型类型上使用where T: struct约束 Note that, despite its name, this doesn't force your type to be a structure; 请注意,尽管名称不同,但这并不会强制您的类型成为结构; it simply forces it to be a value type. 它只是强迫它成为一种价值类型。
  • There is no way for you specify a constraint on the generic type that it must be an enumerated type; 您无法在泛型类型上指定它必须是枚举类型的约束; if you pass some other value type into the method, it will throw an exception at run-time. 如果您将其他值类型传递给方法,它将在运行时抛出异常。 It's up to you to handle this case properly. 由你来正确处理这个案子。

Here's a working (as in -- it compiles -- I haven't actually tested it) version of the code snippet you want. 这是你想要的代码片段的工作(如在 - 它编译 - 我还没有实际测试过)。 However, I will point out that every one of the problems in your original code would be worked out just by reading and understanding the error messages; 但是,我将指出原始代码中的每个问题都可以通过阅读和理解错误消息来解决; this is one of the most important skills you should get good at as a C# developer. 这是作为C#开发人员应该擅长的最重要的技能之一。

static void ReadMenuInput<T>(out T menuInput) where T : struct
{           
  while (true)
  {
    if (Enum.TryParse<T>(Console.ReadLine(), out menuInput)
     && Enum.IsDefined(typeof(T), menuInput))
    {
      break;
    }

    Console.WriteLine("Please enter a valid input.");
  } 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM