使用字符串变量访问常量

本文关键字:访问 常量 变量 字符串 | 更新日期: 2023-09-27 18:36:59

我正在使用 C# 开发 Unity,我编写了一个脚本,如果我可以使用字符串变量访问常量,这将使我的生活更简单。

public class Foo
{
    public const string FooConst = "Foo!";
    public const string BarConst = "Bar!";
    public const string BazConst = "Baz!";
}
// ...inside some method, somewhere else
public string Bar(string constName)
{
    // is it possible to do something like this?
    // perhaps with reflections?
    return Foo.GetConstant(constName);
}

我唯一的解决方案是创建一个在switch内获取常量的方法。但是每次我添加新常量时,我都必须修改该switch

有趣的事实:我是一个进入 C# 的 PHP 孩子。我喜欢它非常严格,强类型之类的东西...但这也使事情变得不必要地复杂。

使用字符串变量访问常量

这使用反射:

var value = typeof ( Foo ).GetFields().First( f => f.Name == "FooConst" ).GetRawConstantValue();

您当然可以使用反射来做到这一点,但恕我直言,更好的选择是将常量存储在字典或其他数据结构中。这样:

public static class Foo
{
    private static Dictionary<string,string> m_Constants = new Dictionary<string,string>();
    static Foo()
    {
        m_Constants["Foo"] = "Hello";
        // etc
    }
    public static string GetConstant( string key )
    {
        return m_Constants[key];
    }
}
public string Bar( string constName )
{
    return Foo.GetConstant( constName );
}

显然,这是一种简化。如果您传递不存在的密钥等,它会引发异常。

你可以尝试以这种方式进行反射

var constExample= typeof(Foo).GetFields(BindingFlags.Public | BindingFlags.Static |
               BindingFlags.FlattenHierarchy)
    .Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.Name==constName).FirstOrFefault();

其中constName是您正在寻找的常量

有关FieldInfo属性的文档,请参阅此处。

如您所见,我已经过滤了IsLiteral = 真和IsInitOnly = 假

  • IsLiteral

获取一个值,该值指示该值是否在编译时写入 并且无法更改。

  • IsInitOnly

获取一个值,该值指示字段是否只能在正文中设置。 的构造函数。

是的,你必须使用反射。喜欢这个:

public string Bar(string constName)
{
    Type t = typeof(Foo);
    return t.GetField(constName).GetValue(null));
}