将枚举名称分配给常量变量

Assign Enum names to const variable

我目前正在尝试将特定枚举中的名称分配给一个字符串,以便我可以在输出到控制台的帮助文档中使用它。这很容易通过以下方式完成:

public string names = string.Join(", ", Enum.GetNames(typeof(LicenseType)));

我的问题是我使用的是 Command Line Parser Library,它需要将每个选项的帮助文本指定为属性参数 (HelpText),它必须是 "constant expression, typeof expression or array creation expression of an attribute parameter type".如何使用 names 的示例:

[Option('t', "license-type", Required = true, HelpText = names)]

但是,当我尝试使用上面的代码将枚举名称分配给 const string 时,编译器抱怨表达式不是常量。

有什么解决办法吗?

枚举是编译时常量,但编译器不保证对 string.Join 的方法调用会产生常量值,因为它与 Enum.GetName.

由于您的枚举是编译为常量,因此您需要将值硬编码到您的属性中。

问题是即使 enums 可能是编译时常量,任何 代码,包括上面实际获取这些名称的代码,都是 not 常数,因为它需要的评估不仅仅是简单的原始值。因此,不可能在需要 string.

Attribute 中使用 enum 名称

但是,如果 OptionAttribute 不是 sealed,您可以定义一个继承的 Attribute class,它接受一个期望枚举的参数,然后通过上面的代码为base(string)。使用此 Attribute,库应将其视为 OptionAttribute,即使您已将其传递给 enum 值。见以下代码:

public class EnumHelpTextAttribute // Always postpend the word "Attribute" to an attribute class
                                   // The compiler cleans this suffix when you actually use the Attribute
    : OptionAttribute
{
    public EnumHelpTextAttribute(LicenseType value)
        : base(string.Join(", ", Enum.GetName(typeof(LicenseType), value)))
    {
    }
}
// ...
[EnumHelpText(LicenseType.Restricted)]  // Or some other value in LicenseType...

遗憾的是,已经注意到 OptionAttribute class sealed,这会阻止创建继承者。然而,作为一个开源项目,可以分叉源代码,解封 class,并因此使用上述建议。一如既往,记录使用情况并返回一个 pull request - 有一天这可以很容易地为其他人省去麻烦!

昨晚睡了一觉之后,解决方案实际上很明显(不是总是这样吗!):只需使用字符串替换...

class Options
{
    private static string LicenseTypeHelp = "License type (" + string.Join(", ", Enum.GetNames(typeof(CompanyLicenseType))) + ").";

    [Option('t', "license-type", Required = true, HelpText = "License type.")]
    public CompanyLicenseType LicenseType { get; set; }    

    [HelpOption('h', "help", HelpText = "Dispaly this help screen.")]
    public string GetUsage()
    {
        string helpText = HelpText.AutoBuild(this, current => HelpText.DefaultParsingErrorsHandler(this, current));
        return helpText.Replace("License type.", LicenseTypeHelp);
    }
}