【问题标题】:Typesafe enum or attribute enum?类型安全枚举或属性枚举?
【发布时间】:2013-12-17 17:42:12
【问题描述】:

我的第一种方法看起来效果很好,直到我遇到运行时错误,我不知道如何在var name = ((LCData)attributes[0]).Name; 解决关于索引超出范围的问题。实际上,我只是在复制我在Getting attributes of Enum's value 找到的代码,所以我不能 100% 确定它实际上做了什么。因此,当以下代码不起作用时,我转向另一个解决方案。

public enum Identification : ushort

{

    [LCAttribute("IMG_BG01_Greens")]
    BG01_Greens = 0,

    [LCAttribute("Rabbit", "IMG_E01_Rabbit")]
    ENEMY_E01_Rabbit = 2000,
}

public static class Enums
{
    public static LCData GetInfo(Identification id)
    {
        var type = typeof(Identification);
        var memInfo = type.GetMember(id.ToString());
        var attributes = memInfo[0].GetCustomAttributes(typeof(LCData), false);
        var name = ((LCData)attributes[0]).Name;
        var tex = ((LCData)attributes[0]).Texture;

        LCData data;
        data.Name = name;
        data.Texture = tex;
        return data;
    }
}

public struct LCData
{
    public string Name;
    public string Texture;

    public LCData(Identification id)
    {
        this = Enums.GetInfo(id);
    }
}

public class LCAttribute : System.Attribute
{
    private string _Name;
    public string Name
    {
        get
        {
            return _Name;
        }
    }

    private string _Texture;
    public string Texture
    {
        get
        {
            return _Texture;
        }
    }

    public LCAttribute(string texture)
    {
        _Texture = texture;
    }

    public LCAttribute(string name, string texture)
    {
        _Name = name;
        _Texture = texture;
    }
}

其次,我尝试了类型安全枚举方法。这有两个我找不到解决方案的致命弱点:

1) 我无法获得用于循环操作的可用枚举条目列表。

2) 我无法通过 id 号获取对应的枚举条目。

public sealed class Identification
{

    private readonly ushort _ID;
    private readonly string _Name;
    private readonly string _Tex;

    public static readonly Identification BG01_Greens = new Identification(0, "IMG_BG01_Greens");
    public static readonly Identification ENEMY_E01_Rabbit = new Identification(2000, "Rabbit", "IMG_E01_Rabbit");

    private Identification(ushort id, string tex)
    {
        _ID = id;
        _Tex = tex;
    }

    private Identification(ushort id, string name, string tex)
    {
        _ID = id;
        _Name = name;
        _Tex = tex;
    }
    public ushort ID { get { return _ID; } }
    public string Name { get { return _Name; } }
    public string Texture { get { return _Tex; } }
}

我应该如何进行?为什么我的第一个解决方案不起作用?

【问题讨论】:

标签: c# enums attributes typesafe


【解决方案1】:

您混淆了LCDataLCAttriubte。因为LCAttribute 是一个有效的属性,但您尝试使用LCData 作为属性。 (顺便说一句,您可能不需要两种不同的类型……但我容忍您)。

这是修改后的代码:

public enum Identification : ushort
{
    [LCAttribute("IMG_BG01_Greens")] //Look the type of the attributes is LCAttribute
    BG01_Greens = 0,

    [LCAttribute("Rabbit", "IMG_E01_Rabbit")]
    ENEMY_E01_Rabbit = 2000,
}

public static class Enums
{
    public static LCData GetInfo(Identification id)
    {
        var type = typeof(Identification);
        var memInfo = type.GetMember(id.ToString());
        //this will return an array of LCAttributes
        var attributes = memInfo[0].GetCustomAttributes(typeof(LCAttribute), false);
        //I tell you they are LCAttribute not LCData
        var name = ((LCAttribute)attributes[0]).Name;
        var tex = ((LCAttribute)attributes[0]).Texture;
        //If the above were an LCData why would create a new one here? [Rethorical]
        LCData data;
        data.Name = name;
        data.Texture = tex;
        return data;
    }
}

注意:对于替代方法以及对这种方法的一些见解,您可以查看my answer to How do you make an 'enum' that has data tied to it?。您在此处使用的方法列在“自定义属性”下。

【讨论】:

  • 我之前尝试将其转换为 LCAttribute 但它给出了索引超出范围错误所以在绝望的尝试中我也尝试将其转换为 LCDData (遵循复制的代码版本),但现在看来我的问题可以通过一个简单的字典来解决,谢谢帮助!
  • @user3110376 如果您的索引超出范围,这可能意味着您无法读取该属性,就好像它不存在一样。链接答案中的替代方案对这种情况进行了一些额外的检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-16
  • 2011-02-16
  • 2019-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多