【问题标题】:look up constants based on value根据值查找常量
【发布时间】:2010-04-02 19:21:16
【问题描述】:

我有一个由以下组成的第 3 方结构:

[StructLayout(LayoutKind.Sequential, Size=1)]
public struct BigBlueReasonCodes
{
    public const int ABC_REASONCODE_DESCRIPTION001 = 1000;
    public const int ABC_REASONCODE_DESCRIPTION002 = 1005;
    public const int ABC_REASONCODE_DESCRIPTION003 = 1010;
    public const int DEF_REASONCODE_DESCRIPTION004 = 2001;
    public const int DEF_REASONCODE_DESCRIPTION005 = 2010;
    public const int DEF_REASONCODE_DESCRIPTION006 = 2013;
    public const int GHI_REASONCODE_DESCRIPTION007 = 3050;
    public const int GHI_REASONCODE_DESCRIPTION008 = 3050;
    public const int GHI_REASONCODE_DESCRIPTION009 = 3052;
    public const string JKL_REASONCODE_DESCRIPTION010 = "XYZ";
    public const string GHI_REASONCODE_DESCRIPTION011 = "ST";


  static BigblueReasonCodes();
}

我正在尝试根据原因代码(值)查找原因描述(字段名称),以便我的班级可以执行以下操作:

string failureReason = GetReasonDescription(reasoncode);

需要提及的是一些具有 int 值和一些具有字符串值。 我只担心具有 int 值的那些。 如果可能,我也只想要以 GHI_ 开头的那些,但不是什么大问题。

【问题讨论】:

  • 我看到他们很友善,有一个值意味着多件事,所以 3050 可能意味着 GHI_...007 和 GHI_...008 伙计哦伙计。

标签: c# struct


【解决方案1】:

您可以通过分析结构使用反射来解决它:

public string GetReasonDescription(int reasonCode)
{
    return
        typeof(BigBlueReasonCodes)
            .GetFields(BindingFlags.Public | BindingFlags.Static)
            .Where(field => field.FieldType == typeof(int)) // Filter int values
            .Where(field => field.Name.StartsWith("GHI"))
            .Where(field => (int) field.GetValue(null) == reasonCode)
            .Select(field => field.Name).First(); // Assuming a field must exists
}

用法示例:

[Test]
public void GetReasonDescriptionTest()
{
    string reasonDescription = GetReasonDescription(3050);
    Assert.That(reasonDescription, Is.EqualTo("GHI_REASONCODE_DESCRIPTION007"));
}

【讨论】:

  • +1:您可能想使用 GetFields(BindingFlags.Public|BindingFlags.Static) 来返回静态的公共字段...
  • @Reed Copsey,谢谢!它描述得更好,更安全。相应地更新了我的答案。
  • 完美!非常感谢。由于代码具有多个描述,我刚刚返回 IEnumerable 并显示所有匹配项。我猜这些代码实际上是像 if (rc==REASONCODE_DESCRIPTON) 一样消费的。
【解决方案2】:

看起来你的整数常量应该是一个enumeration(或多个枚举)——这也将允许与整数相互转换。

您可以通过反射来做到这一点,但它会比转换为枚举慢。

【讨论】:

  • 枚举出来了,因为同一个代码有多重含义。
  • @乔尔。除了现有代码之外,您是否使用枚举或常量应该是一个推动。正如你不能有两个同名的常量一样,你不能有两个同名的枚举。
【解决方案3】:

如果你将整数值填充到枚举而不是常量中,你可以这样做

public enum BigBlueReasonCode
{
    ABC_REASONCODE_DESCRIPTION01 = 1000,
    ABC_REASONCODE_DESCRIPTION01 = 1005,
    ABC_REASONCODE_DESCRIPTION01 = 1010,
    DEF_REASONCODE_DESCRIPTION01 = 2001,
    DEF_REASONCODE_DESCRIPTION01 = 2010,
    DEF_REASONCODE_DESCRIPTION01 = 2013,
    GHI_REASONCODE_DESCRIPTION01 = 3050,
    GHI_REASONCODE_DESCRIPTION01 = 3051,
    GHI_REASONCODE_DESCRIPTION01 = 3052
}

var failureCode = Enum.GetName( reasoncode )

(当然,这段代码不会按原样工作,因为名称中有重复项,但它也不会编译为常量。)

【讨论】:

  • 我假设这种情况下的“reasonCode”是数字。即,用户传入 Enum.GetName(2010)。
  • 请在 cmets 前加上 @Steve,以便我收到通知。如果它是一个非标志枚举并且它被设置为其定义的值之一,那么 reasoncode.ToString() 返回名称。如果它不是定义的值之一,则返回数字。对于标志枚举,它实际上在返回以逗号分隔的选定选项列表方面做得非常好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多