所以,这其实是这个问题是我目前的重点。 我的工作我的个人项目的重构,试图提高性能,优化内存使用,使代码简单明了。 我有一个不同的应用层(实际上,DAL,BLL,ServiceAgents这是WCF服务)。 我使用实体/型号/ DTO的传递那些层,它们是无状态之间的数据(不必在所有的任何逻辑)。 目前,这是这样的一个对象
public class Person
{
public ComplexId Id { get; set; }
public string Name { get; set; }
// ...
}
我用这样的方式,它就像一个“最佳实践”,是吗? 是存储传输的数据这种方式吗? 如果我改变了这样的结构是什么:
public struct Peson
{
public ComplexIdentifier ComplexId;
public string Name;
}
public struct ComplexIdentifier
{
public int LocalId;
public int GlobalId;
}
这将是更好的性能,从/内存使用的角度呢? 或者,也许有某种作用这样的陷阱?
对于标准的DTO实体,你会想坚持的类。
一个struct
具有潜在的应用情况下比一类范围很有限 。 也有效率问题时, struct
类型得到过大(不要忘了,他们是值类型和周围时,通过复制 ),如列出有关值类型MSDN准则 。 且不说很多陷阱,当你开始有struct
通过属性暴露类型,或不小心参考接口箱时,或使它们可变...
我不是说不能使用 struct
时,它是相关的,但我很少发现自己需要使用的struct
在我们的主要桌面应用程序类型-这是分层的,并设有DTO类型。
性能问题不能回答简单,如
struct
与
class
。 你需要使用一个分析工具,例如dotTrace或ANTS ,以便找到热点,并从那里走。 性能问题是不平凡的,良好的工具通常是答案的开始。
The two best choices for a data transfer object should generally be either a deeply-immutable class object, or a struct with exposed fields of types suitable for use as data transfer objects. Other types of structs may sometimes be usable as well, but exposed-field structs are by far the simplest, and that simplicity is a great virtue.
The notion that mutable structs are evil dates back to some early C# compilers which in which
SomeReadonlyStruct.SomeProperty = 5;
would be silently transformed by the compiler into:
var temp = SomeReadonlyStruct;
temp.SomeProperty = 5;
Hiding struct fields behind readonly properties was an attempt to ensure the former statement would refuse to compile instead of yielding broken code. Since newer compilers will refuse to mutate writable fields of readonly structs, there's no longer any need to wrap fields in read-only properties.
Structs with exposed fields have a huge advantage compared with other types of data transfer objects: every struct which has exposed fields of types suitable for data-transfer and no other members else except perhaps a constructor behaves the same way, with no surprises. Someone who has never used structs might be a little surprised by the fact that they don't act like classes, but someone who understands how any such struct works will understand how they all work.
Consider the following code:
customerPhone = someDataSource.GetPhoneNumber(customerID);
customerPhone.Extention = "5309"
Some people dislike the fact that if customerPhone
is an exposed-field struct, setting the Extension
property won't affect the information in someDataSource
. While it's certainly true that writing a struct field won't update anything else, that's a much better situation than would exist if customerPhone
were a mutable class type. Anyone who understands that customerPhone
is an exposed-field struct type will know that changes to its members won't affect anything else. By contrast, if customerPhone
is a mutable class type, code like the above might update someDataSource
by changing the phone number associated with that customerID
. Or it might not. Or, if one phone number was associated with two customerID
values, the above code might change both of them. The amount of code one may have to study to determine exactly what effects and side effects the above code might have would be quite large. Worse, it may be difficult to be sure that one hasn't missed anything.
There are definitely some places where passing around class object references can be more efficient than passing around structs. There are also a few cases where mutable class objects can be useful data holders within a class. Some generic wrappers, however, can faclitate wrapping a struct in a mutable or immutable class, and exchanging the information between those types of classes.
interface IReadableHolder<T> { T Value {get;} }
class MutableHolder<T> : IReadableHolder<T>
{
public T Value;
IReadableHolder.Value {get {return Value;} }
public MutableHolder(T newValue) { Value = newValue; }
public MutableHolder(IReadableHolder<T> it) { Value = it.Value; }
}
class ImmutableHolder<T> : IReadableHolder<T>
{
T _Value;
public Value {get {return _Value;} }
public ImmutableHolder(T newValue) { _Value = newValue; }
}
Such a construct would be much more awkward without mutable structs.
这将是更好的性能,从/内存使用的角度呢?
号结构是值类型,所以他们按值复制。 这意味着,而不是抄袭只是一个参考,你总是会复制完整的对象。 如果有的话,它可能会稍微慢一点,并使用更多的内存(因为对象将复制)。
另一个原因,你should't做到这一点:可变的结构应始终避免,因为它们会导致意外的行为,如果你不小心。
一个struct
可能会更危险的是,值类型是由更多的不同的处理CLR
,如果写得不好(例如一个可变的结构)可以创建可怕的头痛。 另外,如果您的类型包含许多字段,然后从方法传递给方法,你将在每个方法调用从而利用更多的内存,如果你已经在第一时间使用的类被复制的每个字段的值 。
使用DTO (数据传输对象),这将鼓励状态和行为的分离。 这可以是一个很好的设计是否得当(在大多数情况下,你会使用类,而不是结构实现这个模式)。
此外,使用的特定情况下struct
作为DTO object
似乎有缺陷的,因为它引入了不必要的redundancy
。 由于structs cannot inherit other structs
,你无法表达的是,一个关系。 当你有你是做什么Customer
,从继承Person
。 你重复所有的Person properties in the Customer
结构? 你嵌套Customer结构内部人结构? 这两种方法都不理想。 如果您至少使用的类, 你可以有客户延长人 。
你应该使用类的方法,该方法结构甚至可能会比较慢,因为结构是值类型和副本将等。无论您将它们作为函数的参数。 因此,对于你的DTO坚持带班的形式给出。
我的看法是:类是更好的。
随着类可以实现INotifyPropertyChanged接口,如果你做的是什么数据绑定将是非常有益的。
你也可以有像“ID”只“得到” - 属性一些私人领域,你可以将某些方法添加到您的类,你可以让你的实体序列化。
所有我想说的是,你是用类更加灵活,我不认为有在这种情况下,结构和类之间的巨大性能差异。
这里是一个非常不错的书,对我帮助很大,通过设计n层的应用程序: http://msdn.microsoft.com/en-us/library/ee817644.aspx
看看那里。 它说:“结构和类之间的选择对于不包含分层数据或集合,考虑定义一个结构来表示业务实体简单的业务实体对于复杂的业务实体,或要求继承的业务实体,定义实体。一类来代替。”
文章来源: DTO classes vs. struct