问题
I need to create some DTO classes to transport our business objects across WCF.
Since these are just bags of data with no functionality, is there any reason I can't just use fields, or is there some good reason to expose them properly as properties?
//fields
[DataContract]
class CustomerDTO
{
[DataMember] public int Id;
[DataMember] public string Name;
}
//or properties?
[DataContract]
class CustomerDTO
{
[DataMember] public int Id { get; set; }
[DataMember] public string Name { get; set; }
}
回答1:
I mostly favour immutable DTOs with read-only fields if I can get away with it:
public class CustomerDTO
{
public CustomerDTO(int id, string name)
{
Id = id;
Name = name;
}
public readonly int Id;
public readonly string Name;
// Override Equals and GetHashCode as well...
}
There's lots of advantages to be had from immutable records, such as structural equality, which makes automated test assertions much simpler to write. It also dispenses with the need to write and maintain separate Test Data Builders.
It depends on the serializer, though. JSON.NET can handle immutable records, but many other serializers can't.
For those that handle public fields, I prefer fields over properties, simply because it's more honest; automatically implemented read/write properties provide no encapsulation.
Some serializers insist on public properties, and don't serialize fields. If that's the scenario, you have to go with that.
Honestly, considering how much thought I've put into this, it's not really something that keeps me awake at night, because ultimately, at the boundaries, applications aren't object-oriented. Thus, the rules of OOD don't really apply to DTOs anyway.
回答2:
Since these are just bags of data with no functionality, is there any reason I can't just use fields
There are no strong arguments against public fields here. But do realize that it is only because there is no logic (behaviour) inside the DTOs so that the normal argument of encapsulation doesn't hold.
I would still prefer properties but they're not really necessary here.
回答3:
You can use either. Since it doesn't affect performance, you'd be safer off going with properties in case you run into some serialization framework or similar that doesn't work with public fields.
Note that WCF proxy generation will create those DTOs on the client side with public properties and their backing private fields, even if you use public fields on the service side. If you somehow don't want that, you need to share a DTO library between the service and the client.
回答4:
The DataMember
attribute will work with both public fields and properties, so either would be possible. However, I would recommend sticking with properties.
In particular, if you are using StyleCop, then you would be breaking rule SA1401.
The reason for this rule's existence doesn't really apply in your case, but it would still be a maintenance problem if you are running StyleCop validation as part of a build on a continuous integration server.
回答5:
Here are two advantages of properties over fields that I didn't see anyone else mention.
- Friction in syntax properly matches capabilities
I think the default behavior should be the safer option. For fields, the default behavior allows for mutability, which is the more dangerous option. The keyword readonly
must be added to make a field immutable (outside of constructors). In contrast, the default state of an auto property is immutable; the syntax set;
must be added in order for the property to be mutable (outside of constructors).
- Reference count given in Visual Studio's Code Lens
Unlike a field, viewing a property in Visual Studio has a "Code Lens", which includes its reference count. I am able to understand and refactor a property more quickly than a field because of this additional information. Of course, one can search in Visual Studio for references to things like fields and properties using Shift+F12, but that is an extra step that takes time. Moreover, in rare cases, some projects include multiple targets. This makes the Shift+F12 search results more difficult to use because there is a search is performed for every target. In contract, the reference count given in a property's Code Len is independent of the number of project targets.
Conclusion
To directly answer the question though, I prefer to use mutable properties (and no explicit constructors) in order to ensure I will be using the happiest of happy paths in the serialization library (which was mentioned in the answer of @ErenErsönmez).
回答6:
I'd never expose fields directly, most companies prohibit this in their standards. Effectively you totally throw away encapsulation. DTOs, being anemic representations of something more complex are an odd case as their properties pretty much break encapsulation anyway. Personally, I'd use the properties as that's what they're there for. It also lets you implement "dirty" functionality etc. if you need to which isn't so easy if you're tweaking fields directly.
来源:https://stackoverflow.com/questions/10831314/dtos-properties-or-fields