hel*_*ker 11 c# enums structure
我有一个恒定的数据结构,代表每个人类椎骨的相对高度,相对于总脊柱高度标准化.这来自人体测量学等.
我已经在Python中实现了它作为元组的元组,每个元组包含一个(字符串)Name和(double)Value,如下所示:
vertebral_heights = (
("C7", 0.0000000),
("T1", 0.0391914),
("T2", 0.0785479),
("T3", 0.1183993),
("T4", 0.1590759),
("T5", 0.2009076),
("T6", 0.2442244),
("T7", 0.2893564),
("T8", 0.3366337),
("T9", 0.3863861),
("T10", 0.4389439),
("T11", 0.4946370),
("T12", 0.5537954),
("L1", 0.6167492),
("L2", 0.6838284),
("L3", 0.7553630),
("L4", 0.8316832),
("L5", 0.9131188),
("S1", 1.0000000))
Run Code Online (Sandbox Code Playgroud)
我的第一个想法是创建一个Dictionary,但是需要一个类作为容器.然后想到了一个Enum的想法,但我读过"enums for ints",而且我有双打.然后是Class和Struct,但到目前为止我完全感到困惑,我相信我目前对用C#做这些东西的最佳实践的理解还不够.
我的用途是在应用程序模型(元素的数字部分)和用户模型(元素的命名,域相关部分)之间建立"映射".
有什么建议吗?
这实际上取决于您希望如何访问这些值.
常量
如果您将始终使用变量名称,例如:
double x = C7;
Run Code Online (Sandbox Code Playgroud)
那么你可以使用一个充满常量的类,如下所示:
public class VertebralHeights
{
public const double C7 = 0.0000000d;
}
Run Code Online (Sandbox Code Playgroud)
字典
但是,如果要动态访问它们,例如:
string id = "C7";
double x = VertebralHeights[id];
Run Code Online (Sandbox Code Playgroud)
那么你最好用Dictionary你可以定义的那样:
Dictionary<string, double> VertebralHeights = new Dictionary<string, double>()
{
{ "C7", 0.0000000d },
{ "T1", 0.0391914d}
}
Run Code Online (Sandbox Code Playgroud)
两种方式在一起.
如果您希望对值进行强类型和动态访问,则可以扩展上述任一方法...
对于常量(方法1),添加一个带字符串的函数:
public double GetValue(string s)
{
switch(s)
{
case "C7": return C7;
case "T7": return T7;
//...and so on...
default: return 0;//or an alternate default
}
}
Run Code Online (Sandbox Code Playgroud)
(注意:你可以用反射来做这件事,这对于一个庞大的列表来说会更容易,但这并不值得在这里获得额外的性能)
对于Dictionary方法(方法2),您可以添加一组getter:
public double C7 { get { return VertebralHeights["C7"]; } }
Run Code Online (Sandbox Code Playgroud)
这是我对此的看法 - 使用单例类,它是一个字典:
public class Vertebrae : Dictionary<string, double>
{
private Vertebrae() : base() { }
private static Vertebrae _heights = new Vertebrae() {
{ "C7", 0.0 },
{ "T1", 0.0391914 },
{ "T2", 0.0785479 },
};
public static Vertebrae Heights { get { return _heights; } }
public static double C7 { get { return Heights["C7"]; } }
public static double T1 { get { return Heights["T1"]; } }
public static double T2 { get { return Heights["T2"]; } }
public static IEnumerable<double> All
{
get
{
return new List<double>() { C7, T1, T2 };
}
}
}
Run Code Online (Sandbox Code Playgroud)
要按字符串名称访问Vertebrae,您可以:
double c7 = Vertebrae.Heights["C7"];
Run Code Online (Sandbox Code Playgroud)
要通过符号名称访问Vertebrae,您可以:
double c7 = Vertebrae.C7;
Run Code Online (Sandbox Code Playgroud)
要枚举您的Vertebrae,您可以:
foreach (double v in Vertebrae.All) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
对于枚举器,您可以在枚举器中初始化一个静态List,但我不确定哪个会先被初始化,静态列表或静态字典...
做为一个枚举,并预先编写黑匣子管道代码。你不会后悔的!这就是我要做的:
编写一个自定义属性,以便可以将double值与每个枚举关联:
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
internal sealed class VertebralHeightAsDoubleAttribute : Attribute
{
public double HeightValue { get; private set; }
public VertebralHeightAsDoubleAttribute(double heightValue_)
{
HeightValue = heightValue_;
}
}
Run Code Online (Sandbox Code Playgroud)
一些扩展方法可以使生活更轻松:
public static class VHAttribExtensions
{
public static string ToNameString(this VertebralHeight target)
{
return Enum.GetName(typeof(VertebralHeight), target);
}
public static double ToHeightValue(this VertebralHeight target)
{
var fi = target.GetType().GetField(target.ToString());
var attributes = (VertebralHeightAsDoubleAttribute[])fi.GetCustomAttributes(
typeof(VertebralHeightAsDoubleAttribute), false);
return attributes.Length > 0 ? attributes[0].HeightValue : double.NaN;
}
}
Run Code Online (Sandbox Code Playgroud)
使用custom属性定义您的枚举:
public enum VertebralHeight
{
[VertebralHeightAsDouble(0.0000000)]
C7,
[VertebralHeightAsDouble(0.0391914)]
T1,
[VertebralHeightAsDouble(0.0785479)]
T2,
[VertebralHeightAsDouble(0.1183993)]
T3,
[VertebralHeightAsDouble(0.1590759)]
T4,
[VertebralHeightAsDouble(0.2009076)]
T5,
[VertebralHeightAsDouble(0.2442244)]
T6,
[VertebralHeightAsDouble(0.2893564)]
T7,
[VertebralHeightAsDouble(0.3366337)]
T8,
[VertebralHeightAsDouble(0.3863861)]
T9,
[VertebralHeightAsDouble(0.4389439)]
T10,
[VertebralHeightAsDouble(0.4946370)]
T11,
[VertebralHeightAsDouble(0.5537954)]
T12,
[VertebralHeightAsDouble(0.6167492)]
L1,
[VertebralHeightAsDouble(0.6838284)]
L2,
[VertebralHeightAsDouble(0.7553630)]
L3,
[VertebralHeightAsDouble(0.8316832)]
L4,
[VertebralHeightAsDouble(0.9131188)]
L5,
[VertebralHeightAsDouble(1.0000000)]
S1
}
Run Code Online (Sandbox Code Playgroud)
测试一下:
static void Main(string[] args)
{
var list = Enum.GetValues(typeof(VertebralHeight)).OfType<VertebralHeight>();
foreach (var vh in list)
{
Console.WriteLine("{0} : {1}", vh.ToNameString(), vh.ToHeightValue());
}
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)