Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 哪个最适合数据存储结构/类?_C#_Class_Struct - Fatal编程技术网

C# 哪个最适合数据存储结构/类?

C# 哪个最适合数据存储结构/类?,c#,class,struct,C#,Class,Struct,我们在SO中看到了很多关于c#中类与结构的讨论。大多数结论是,这是一个堆/堆栈内存分配。并建议在小数据结构中使用structs 现在,我有一个情况来决定这两个选择中的简单数据存储。目前,在我们的应用程序中,我们有数千个类,只是充当简单的数据存储(仅公开的公共字段),它们在不同的模块和服务之间传递 根据我的理解,出于性能方面的考虑,我觉得最好还是使用struct而不是类。因为这些都是简单的数据结构,所以只能作为数据存储 在开始这项工作之前,我需要一些经历过这场斗争的人的专家建议 我的理解正确吗

我们在SO中看到了很多关于c#中类与结构的讨论。大多数结论是,这是一个堆/堆栈内存分配。并建议在小数据结构中使用structs

现在,我有一个情况来决定这两个选择中的简单数据存储。目前,在我们的应用程序中,我们有数千个类,只是充当简单的数据存储(仅公开的公共字段),它们在不同的模块和服务之间传递

根据我的理解,出于性能方面的考虑,我觉得最好还是使用struct而不是类。因为这些都是简单的数据结构,所以只能作为数据存储

在开始这项工作之前,我需要一些经历过这场斗争的人的专家建议

  • 我的理解正确吗
  • 我看到大多数orm都有类作为数据存储。因此,我怀疑是否有理由继续使用类而不是结构。那会是什么

结构应定义为不可变,而类中不应定义为不可变。如果你认为你的对象将变得小而不可变,你可以继续把它们做成结构,或者让它们成为类。

我似乎永远都记不清结构到底有什么不同,但它们确实不同。以微妙的方式。事实上,有时它们会来咬你

所以。除非你知道自己在做什么,否则就坚持上课

我知道这听起来有点像新手。我知道我现在应该去查找差异并在这里显示它们——但其他人已经这样做了。我所说的是,添加一种不同类型的对象会造成语义上的负担,还有一点额外的复杂性,你应该慎重考虑。

如果我没记错的话,最大的问题之一是结构的值语义:传递它们将导致不同的对象(当它们通过值传递时)。如果您在一个地方更改了某个字段,请注意,在所有其他地方,该字段都没有更改!这就是为什么每个人都推荐结构的不变性


编辑:对于您描述的案例,结构将不起作用

关于结构不可变的评论是正确的。这就是它可以咬你的地方。您可以使用字段设置器定义结构,但当您更改字段值时,将创建一个新实例。因此,如果保留对旧对象的引用,它仍将引用旧值。出于这个原因,我不喜欢使用可变语句,因为这会产生微妙而复杂的bug(特别是如果使用复杂的复合语句)


另一方面,使用具有不可变状态的类也有很多很好的理由(想想字符串)。

我会根据以下标准做出选择

  • 引用类型与值类型语义。如果两个对象只有在它们是相同对象时才相等,则表示引用类型语义=>class。如果其成员的值定义了相等性(例如,如果两个DateTimes表示相同的时间点,即使它们是两个不同的对象,则两个DateTimes是相等的),则值类型语义=>struct
  • 对象的内存占用。如果对象很大并且经常被分配,那么将其作为结构将更快地消耗堆栈,因此我宁愿将其作为类。相反,我宁愿避免对小值类型的GC惩罚;因此,使它们成为一个结构
  • 你能使对象不可变吗?我发现结构非常适合“值对象”——来自DDD书籍
  • 您是否会因为使用此对象而面临拳击拆箱处罚?如果是,就去上课

我记得MSDN上给出的一条建议,结构不应大于16或21字节。正在查找链接,但尚未找到


其主要含义是,一旦您的数据类型中有了字符串,就可以不用思考就将其作为类。否则,结构不应该容纳太多。

我认为您的想法是正确的。结构用于模拟数据类型。它们是价值驱动的,而不是基于参考的。如果您查看大多数基本数据类(int、double、decimal等)的MSDN文档,它们都是基于结构的。尽管如此,结构不应该因为同样的原因被过度使用。存储该结构中所有内容的空间在实例化后立即分配,其中as类只分配空间用于引用其中的所有内容。如果数据在足够小的块中,而这不是问题,那么结构就是解决方法。如果这是一个问题,就去上课。如果您不知道,最好还是坚持您熟悉的内容。

类对象的优点是可以传递对它的引用,如果引用到达外部代码,则此类引用的范围和生存期是无限的。结构的优点是,虽然可以传递对它们的短期引用,但不可能传递永久的混杂引用。这有助于避免担心是否存在此类引用

有些人建议可变的数据持有者不应该是结构。我完全不同意。在许多情况下,为了保存数据而存在的实体应该是结构化的,特别是当它们是可变的时。Eric Lippert多次发布他认为可变值类型是邪恶的(在标记“mutable”和“struct”下搜索)。确实,.net允许使用不应该使用的可变结构完成某些事情,也不方便使用它应该使用的某些事情,但是POD(“普通旧数据”)结构没有变异方法,而是通过公共字段公开其整个状态,它们的行为具有非常有用的一致性,这是任何其他数据类型都无法共享的。使用POD结构可能会使不熟悉其工作方式的人感到困惑,但会使程序变得复杂 [employeeInfoStruct is a struct containing the following field] public Decimal YearlyBonus; [someEmployeeContainer is an instance of a class which includes the following method] EmployeeInfoStruct GetEmployeeInfo(String id); // Just the signature--code is immaterial [some other method uses the following code] EmployeeInfoStruct anEmployee = someEmployeeContainer.GetEmployeeInfo("123-45-6789"); anEmployee.YearlyBonus += 100;
public struct Person
{
    public DateTime Birthday { get; set; }
    public int Age{ get; set; }
    public String Firstname { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Person p1 = new Person { Age = 44, Birthday = new DateTime(1971, 5, 24), Firstname = "Emmanuel" };
        Person p2 = new Person { Age = 44, Birthday = new DateTime(1971, 5, 24), Firstname = "Emmanuel" };
        Debug.Assert(p1.Equals(p2));
        Debug.Assert(p1.GetHashCode() == p2.GetHashCode());
    }
}