创建一个简单的数据容器类时,应该是什么?
上述例子:
struct MutableStruct
{
public string Text { get; set; }
public int Number { get; set; }
}
struct ImmutableStruct
{
public string Text { get; private set; }
public int Number { get; private set; }
public ImmutableStruct(string text, int number)
: this()
{
Text = text;
Number = number;
}
}
struct MutableStructWithConstructor
{
public string Text { get; set; }
public int Number { get; set; }
public MutableStructWithConstructor(string text, int number)
: this()
{
Text = text;
Number = number;
}
}
class MutableClass
{
public string Text { get; set; }
public int Number { get; set; }
}
class ImmutableClass
{
public string Text { get; private set; }
public int Number { get; private set; }
public ImmutableClass(string text, int number)
{
Text = text;
Number = number;
}
}
class MutableClassWithConstructor
{
public string Text { get; set; }
public int Number { get; set; }
public MutableClassWithConstructor(string text, int number)
{
Text = text;
Number = number;
}
}
我们应该选择一个高于另一个的好理由吗?或者主要是将主观偏好分开?或者它在很大程度上依赖于特定用例?如果是这样,在哪些用例中你应该选择什么和为什么?
答案 0 :(得分:11)
几乎总是一堂课;结构应该只用于是值的东西 - 例如,复数 - 或货币类型/值对 - 并且应该几乎 - 不包括 - 排除不可变的。
如果要进行数据绑定,无参数构造函数对于可变数据很方便,因为这允许系统在没有自己的附加代码的情况下创建实例。非空构造函数对于不可变数据非常重要。对于可变数据,对象初始值设定项有很长的路要走(尽管在验证方面不是相当相同):
var obj = new Person {Name="Fred", DateOfBirth=DateTime.Today};
您的类型是否不可变取决于您; mutable使得更容易进行数据绑定和序列化。一般来说,您往往会在.NET中看到更多可变类型,但随着我们进入并行/多核时代,这可能会发生变化。
答案 1 :(得分:3)
你几乎总是喜欢类而不是结构。仅当对象表示(不可变)值时才使用结构。
如果您需要更改对象并且这样做是安全的,那么使其变为可变,否则使其变为不可变并使用克隆。
如果使用默认构造函数创建对象时处于有效状态,则很好。否则总是提供自己的构造函数。
答案 2 :(得分:2)
只在需要值类型语义时才使用结构,并尝试完全避免可变结构。
除此之外,我认为这取决于个人,团队,偏好以及您的特殊要求。
(这些天我试图尽可能使用不可变对象,这几乎总是需要将值传递给构造函数。)
答案 3 :(得分:1)
关于类与结构的几点:
类是传递引用,这意味着在函数之间传递相同的实例对象。如果在方法A中创建MyClass并调用方法B,则方法B更改类并且不向方法A返回任何内容,方法A查看在MyClass中所做的更改,因为它们引用了同一个对象。引用通常是一个int32,所以无论你的类有多大,它都会很快调用方法B,因为它只传递4个字节。类依赖于垃圾收集器来决定何时不再使用它(传递类的开销较小,但会增加垃圾收集器的开销)。
结构是值传递(或值类型)。这意味着整个结构在传递时会被复制。如果您的结构很大,这将需要很长时间。方法B中对结构的更改将不会在方法A中显示,除非它被返回(再次按值传递计算时间),并且方法A读取返回值。结构是在堆栈上创建的,没有垃圾收集开销(如果检查IL代码,可以看到这一点)。
与类相比,结构中存在许多限制,例如缺少虚方法和其他多态功能。
最好支持类,除非你要在同一个方法中快速创建和丢弃大量对象(由于垃圾收集导致系统资源耗尽),在这种情况下有利于结构。
答案 4 :(得分:0)
我通常使用构造函数设置/传入所有值来创建不可变类。
答案 5 :(得分:0)
此外,根据经验,结构不应大于16个字节 - 处理器缓存行的大小。
答案 6 :(得分:0)
考虑在需要提供对象“功能”时使用类,而不仅仅是身份或状态,即“值”。
正如已经说过的,结构是值类型,因此将在您使用它们的任何地方进行复制。此外,在实例化类与结构体时,性能差异可以忽略不计。
答案 7 :(得分:0)
看起来几乎所有时间结构都不必分散课程的简易性和效率。