我是否应该使用枚举、静态类、字典或结构来表示这些;“标记浮动”;在C#中?

我是否应该使用枚举、静态类、字典或结构来表示这些;“标记浮动”;在C#中?,c#,enums,structure,C#,Enums,Structure,我有一个恒定的数据结构,表示每个人体脊椎的相对高度,与脊柱总高度相关。这是由人体测量学研究等得出的 我在Python中将其实现为元组的元组,每个元组包含(字符串)名称和(双精度)值,如下所示: vertebral_heights = ( ("C7", 0.0000000), ("T1", 0.0391914), ("T2", 0.0785479), ("T3", 0.1183993), ("T4", 0.1590759), ("T5", 0.2009076), ("T6", 0.2

我有一个恒定的数据结构,表示每个人体脊椎的相对高度,与脊柱总高度相关。这是由人体测量学研究等得出的

我在Python中将其实现为元组的元组,每个元组包含(字符串)名称和(双精度)值,如下所示:

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))
我的第一个想法是创建一个字典,但这需要一个类作为容器使用。然后我想到了枚举的概念,但我读过“枚举代表整数”,我有两个。还有Class和Struct,但到目前为止,我完全感到困惑,我相信我目前对用C#做这件事的最佳实践的理解还不够

我的预期用途是在应用程序模型(元素的数字部分)和用户模型(元素的命名、域相关部分)之间建立一个“映射”


有什么建议吗?

取决于您如何使用这些映射。如果涉及按名称(
string
)进行的任何查找,那么
字典
是正确的选择。但如果您只需要这些数字就可以有友好的名称,我会选择类中的常量(可能是静态的)

在字典中枚举键和值也很容易:

var dict = new Dictionary<string, double>();

foreach (var key in dict.Keys)
{

}

foreach (var value in dict.Values)
{

}
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 };
        }
    }
}
var dict=newdictionary();
foreach(dict.Keys中的var键)
{
}
foreach(dict.Values中的var值)
{
}

您可以创建一个类:

public static class VertebralHeights
{
    public const double C7 = 0.0000000;
    public const double T1 = 0.0391914;
    //...
}

访问:
double c7=脊椎重量.c7

这实际上取决于您希望如何访问这些值

常数

如果始终使用变量名,例如:

double x = C7;
string id = "C7";
double x = VertebralHeights[id];
然后您可以使用一个充满常量的类,如下所示:

public class VertebralHeights
{
    public const double C7 = 0.0000000d;
}
字典

但是,如果要动态访问它们,例如:

double x = C7;
string id = "C7";
double x = VertebralHeights[id];
然后,您最好使用
字典
,您可以这样定义:

Dictionary<string, double> VertebralHeights = new Dictionary<string, double>()
{
    { "C7", 0.0000000d },
    { "T1", 0.0391914d}
}
(注意:您可以使用反射来实现这一点,使用大量列表会更容易,但实际上不值得在这里额外增加性能)

对于Dictionary方法(方法2),您可以添加一组getter:

public double C7 { get { return VertebralHeights["C7"]; } }

以下是我对此的看法-使用一个单件类,这是一个字典:

var dict = new Dictionary<string, double>();

foreach (var key in dict.Keys)
{

}

foreach (var value in dict.Values)
{

}
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 };
        }
    }
}
要通过符号名称访问脊椎,请执行以下操作:

double c7 = Vertebrae.Heights["C7"];
double c7 = Vertebrae.C7;
要列举你的脊椎,你需要:

foreach (double v in Vertebrae.All) { /* ... */ }

对于枚举器,您可以像在枚举器中一样初始化一个静态列表,但我不确定先初始化哪个,静态列表还是静态字典…

要枚举它们,按字符串查找它们,并按顺序排序,您需要存储三条数据。访问它们的方式会改变存储它们的最佳方式

  • 包含名称和值的元组的列表。
    • 这具有订购的主要优势
    • 为了按名称获取特定项,您需要一个linq查询来检索它
  • 字典
    带有名称键和包含顺序和值的元组值
    • 它的主要优点是按名称快速查找项目
    • 为了以特定的顺序获取所有项目,您需要一个linq查询来对它们进行排序
    • 如果您只想在没有特定顺序的情况下循环所有项目,
      Dictionary
      将允许这样做
  • 保留一本字典和一个值列表。-有点混乱,可能是过度优化
  • 创建一个自定义集合,该集合继承自上述实现之一,并提供隐藏实际实现的缺失功能。Linq的速度并没有慢到令人担忧的程度

  • 可以在泛型集合中使用简单类。然后,LINQ可以轻松地将值映射到另一个值

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
    
        class Vertebra {
            public string name { get; set; }
            public double height { get; set; }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                List<Vertebra> Vertebrae = new List<Vertebra>() {
                    new Vertebra() {name = "C7", height = 0.0000000},
                    new Vertebra() {name = "T1", height = 0.0391914}
                    //etc
                };
    
                //find height by name:
                double H = Vertebrae.Single(v => v.name == "C7").height;
    
                //find name by height:
                string N = Vertebrae.Single(v => v.height == 0.0391914).name;
    
            }
        }
    
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用系统文本;
    命名空间控制台应用程序1
    {
    脊椎类{
    公共字符串名称{get;set;}
    公共双倍高度{get;set;}
    }
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    列表脊椎=新列表(){
    新脊椎(){name=“C7”,高度=0.0000000},
    新脊椎(){name=“T1”,高度=0.0391914}
    //等
    };
    //按名称查找高度:
    双H=椎骨。单(v=>v.name==“C7”)。高度;
    //按高度查找名称:
    字符串N=椎骨。单个(v=>v.height==0.0391914)。名称;
    }
    }
    }
    
    将其作为一个枚举,并在前面编写黑盒管道代码。你不会后悔的!下面是我要做的:

    编写自定义属性,以便可以将双精度值与每个枚举关联:

    [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
    internal sealed class VertebralHeightAsDoubleAttribute : Attribute
    {
      public double HeightValue { get; private set; }
    
      public VertebralHeightAsDoubleAttribute(double heightValue_)
      {
        HeightValue = heightValue_;
      }
    }   
    
    让生活更轻松的一些扩展方法:

    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;
      }
    }
    
    使用自定义属性定义枚举:

    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
    }
    
    测试它:

    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();
    }
    
    static void Main(字符串[]args)
    {
    var list=Enum.GetValues(typeof(脊椎高度)).OfType();
    foreach(列表中的var vh)
    {
    Console.WriteLine(“{0}:{1}”,vh.ToNameString(),vh.ToHeightValue());
    }
    Console.ReadLine();
    }
    
    如果您需要动态访问它们(通过标签名),那么字典可能是最好的选择。如果您只是通过变量名引用它们,那么单个类中的一组常量可能就可以了(假设没有那么多)@musefan 1)它们将是静态/常量/只读的;2) 我想从
    IEnumerable
    的意义上保留它们之间的一些“相对顺序”;例如,通过
    获取值。L3
    会很好。对于这么小的集合,列表可能比字典更快。如果性能很重要,则对其进行基准测试。我可以按顺序列举它们吗?类似于值中的
    foreach值
    或标签中的
    foreach标签
    ?该枚举顺序不正确。当然,您需要处理