我有一组包含相关信息的项目。这些项目由我,程序员定义,用户不需要更改它们,它们永远不需要根据配置进行更改,并且它们可能更改的唯一时间是我的应用程序的未来版本。我事先知道应该有多少这些项目,以及它们的确切数据。
一个enum,是一个很好的编程结构,让我可以预定义我的应用程序中可用的一组键,并将它们分组为逻辑类型。
我现在需要的是一个构造,让我可以预定义一组附加了额外信息的键。
示例:
这是标准枚举:
public enum PossibleKeys
{
Key1,
Key2,
Key3
}
这是我需要的枚举:
public enum PossibleItems
{
Item1
{
Name = "My first item",
Description = "The first of my possible items."
},
Item2
{
Name = "My second item",
Description = "The second of my possible items."
},
Item3
{
Name = "My third item",
Description = "The third of my possible items."
}
}
我知道这种枚举不存在。我要问的是:在C#中,如何硬编码一组预定义的项目,其数据是在代码中设置的?最好的方法是什么?
编辑:我不一定想要一个使用枚举的解决方案,只是一个允许我有这种行为的解决方案,即了解我的应用程序中的所有可能项目,以及每个项目都有的信息。
编辑2:能够在运行时获取所有现有项目对我来说很重要。因此,需要能够查询所有项目并迭代它们。就像我能用枚举一样。
答案 0 :(得分:4)
试试这个
public enum PossibleKeys{
[Description("key 1 desc")]
Key1,
[Description("key 2 desc")]
Key2,
[Description("key 3 desc")]
Key3
}
答案 1 :(得分:2)
C#在这方面不是很好 - 枚举往往只是那个,而不是其他的东西。你可以接近以下内容,但我很快就推荐一个带有私有构造函数的类和只读它自己的实例。
class Program
{
static void Main(string[] args)
{
State fullState = State.Full;
Console.WriteLine(fullState.Description());
Console.WriteLine(State.HalfFull.Description());
Console.ReadLine();
}
}
public enum State
{
Empty,
Full,
HalfFull
}
public static class StateExtensions
{
private static Dictionary<State, string> descriptions = new Dictionary<State, string>();
static StateExtensions()
{
descriptions.Add(State.Empty, "It's just empty");
descriptions.Add(State.Full, "It's so full");
descriptions.Add(State.HalfFull, "It's got something in it");
}
public static string Description(this State state)
{
return descriptions[state];
}
}
或者基于非枚举的approched可能类似于
class MusicalNote
{
public int Index { get; private set; }
public string Name { get; private set; }
private MusicalNote(int index, string name)
{
Index = index;
Name = name;
}
public static readonly MusicalNote A = new MusicalNote(1, "A");
public static readonly MusicalNote ASharp = new MusicalNote(2, "A#");
}
答案 2 :(得分:2)
如果纯粹是为了描述,您可以使用其他一些答案中所述的内置DescriptionAttribute
。但是,如果需要属性无法提供的功能,则可以使用某种元数据对象创建查找。
这样的事情:
public enum PossibleKeys
{
Key1,
Key2,
Key3
}
public class KeyMetadata
{
public PossibleKeys Id { get; set; }
public string Description { get; set; }
public SomeOtherClass SomethingAttributesCantHandle { get; set; }
}
private static readonly IReadOnlyDictionary<PossibleKeys, KeyMetadata> KeyMetadataLookup;
static EnumContainerClass()
{
Dictionary<PossibleKeys, KeyMetadata> metadata = new Dictionary<PossibleKeys, KeyMetadata>();
metadata.Add(PossibleKeys.Key1, new KeyMetadata { Id = PossibleKeys.Key1, Description = "First Item" });
metadata.Add(PossibleKeys.Key2, new KeyMetadata { Id = PossibleKeys.Key2, Description = "Second Item" });
metadata.Add(PossibleKeys.Key3, new KeyMetadata { Id = PossibleKeys.Key3, Description = "Third Item" });
KeyMetadataLookup = new ReadOnlyDictionary<PossibleKeys, KeyMetadata>(metadata);
}
然后检索:
KeyMetadataLookup[PossibleKeys.Key1].Description
请注意,如果某些属性无法处理,我只会使用此功能。如果它是所有原始类型,您也可以简单地创建自己的自定义属性。你不仅仅局限于内置的。
您自己的自定义属性最终会像:
[System.AttributeUsage(System.AttributeTargets.Enum)]
public class CustomDataAttribute : System.Attribute
{
public string Name { get; set; }
public string Description { get; set; }
}
然后在使用中:
public enum PossibleItems
{
[CustomData(Name = "My first item", Description = "The first of my possible items.")]
Item1,
[CustomData(Name = "My second item", Description = "The second of my possible items.")]
Item2,
[CustomData(Name = "My third item", Description = "The third of my possible items.")]
Item3
}
答案 3 :(得分:1)
当我需要与枚举值相关联的描述时,我通过在每个枚举值上放置DescriptionAttribute
然后使用扩展方法来获取对该数据的访问权来执行此操作。这是一个完整的LINQPad示例。
// Make sure to add a using for System.ComponentModel
void Main()
{
Test.First.GetDescription().Dump();
Test.Second.GetDescription().Dump();
}
public enum Test
{
[Description("My first enum value's description.")]
First = 1,
[Description("My second enum value's description.")]
Second = 2
}
public static class EnumExtensions
{
public static string GetDescription(this Enum value)
{
DescriptionAttribute[] descriptionAttributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
return (descriptionAttributes != null && descriptionAttributes.Length > 0 ? descriptionAttributes[0].Description : null);
}
}
此输出
我的第一个枚举值的描述。
我的第二个枚举值的描述。
答案 4 :(得分:1)
public class PossibleItems
{
public class Item1
{
public static readonly string Name = "My first item";
public static readonly string Description = "The first of my possible items.";
}
public class Item2
{
public static readonly string Name = "My second item";
public static readonly string Description = "The second of my possible items.";
}
public class Item3
{
public static readonly string Name = "My third item";
public static readonly string Description = "The third of my possible items.";
}
}
使用PossibleItems.Item1.Name;
答案 5 :(得分:1)
另一种替代方法是使用 Java样式枚举
public class PossibleItems
{
public string Name { private set; get; }
public string Description { private set; get; }
public static PossibleItems Item1 = new PossibleItems() { Name = "My first item", Description = "The first of my possible items" };
public static PossibleItems Item2 = new PossibleItems() { Name = "My second item", Description = "The second of my possible items" };
private PossibleItems()
{
}
public override int GetHashCode()
{
return (Name + ";" + Description).GetHashCode();
}
public override bool Equals(object obj)
{
if(!(obj is PossibleItems)) return false;
var other = obj as PossibleItems;
return other.Name == Name && other.Description == Description;
}
}
bool eq = PossibleItems.Item1 == PossibleItems.Item1;
Console.WriteLine(PossibleItems.Item1.Name);
答案 6 :(得分:0)
我同意你应该使用某种类。但是如果你真的想使用Enums,你也可以添加一个扩展方法。
public static PossibleItem GetPossibleItem(this PossibleKey key){
switch (key){
case Key1:
return WhateverItem;
...
}
然后你可以调用Key1.GetPossibleItem();
答案 7 :(得分:0)
static class PossibleItems
{
public class Item
{
public readonly string Name;
public readonly string Description;
public Item(string name, string desc)
{
this.Name = name;
this.Description = desc;
}
}
public static List<Item> Get()
{
List<Item> list = new List<Item>();
list.Add(new Item("name1", "desc1"));
list.Add(new Item("name2", "desc2"));
return list;
}
}
然后以迭代的方式进行访问
foreach ( PossibleItem.Item item in PossibleItems.Get())
{
MessageBox.Show(item.Name + ": " + item.Description);
}
如果您想要一个具有特定名称的项目,您甚至可以将此代码添加到PossibleItems类
public static Item GetItemWithName(PossibleNames name)
{
switch (name)
{
case PossibleNames.Name1:
return new Item("Name1", "Desc1");
case PossibleNames.Name2:
return new Item("Name2", "Desc2");
}
return null;
}
public enum PossibleNames
{
Name1,
Name2
}
P.S。我在智能手机上输入了额外的积分