use attributes to avoid exposing data members directly to the outside world
Learning Research. NET in the early days, often encountered some learning c#/. NET's friend asks, attribute this kind of flashy thing to do what? Later when doing the project also often received the team's complaints feedback, why not put a public field directly? Such as:
Class Card
{
public string Name;
}
And to do a private field +public property
Class Card
{
private string name;
public string Name
{
get {return this.name;}
set {This.name=value;}
}
}
I remember in an earlier project, a friend of the team was even tired of writing private field +public attributes, especially when they ran into a bunch of bloated data object classes, and simply wrote a small tool to provide the field name and type of a class. The corresponding private field +public property is then automatically generated for the class.
I was a complete pragmatist when I was programming, with a slightly more elegant phrase called "dislike of excessive design". If the card is really written like the above, and there is no need for change in the future, I don't like to complicate things deliberately like the 2nd procedure above. But if from the component's point of view, there are always some classes for external long-term use, but also potentially in the future have to change the demand. At this point, it is necessary to provide the attributes.
That's why this item is trying to generalize the use of attributes:
1. Can be assigned to do the calibration, or additional processing
2. Can do thread synchronization
3. You can use a virtual property, or an abstract property
4. Attributes can be placed in interface
5. can provide get-only or set-only version, can even read and write with different access rights (C # 2.0 support)
Personal feeling 3, 4 is the attribute biggest advantage, can fill no "medieval paragraph" or "abstract field" of the flaw, in the design of components is very useful, also embodies the C # such component-oriented language spiritual connotation.
But if there is no such reason, and in the future, the possibility of larger changes in the program is more than an hour, I think it is also not necessary to put each public field into a property. For example, when designing some lightweight struct for interoperability, it's not bad to use the public field directly. So, feel this article Bill Wagner used "Always use Properties Instead of the Accessible Data members" to appear too tough.
In fact, the discussion here also shows that reading "Effective C #" a book to pay attention to, that is, the effective principle is not universal. Different projects (modular, more reusable projects?) A "write once, n years run" project, different roles (class Library/component developer?) Or an application developer? ), there are different effective guidelines. In fact, many of the items in the book are considered from the perspective of the class Library/component developer.
There is a point to be made about the performance of properties, and there is a considerable loss of performance if simply using the attribute in Access mode. Because the inline process has been done during JIT compilation. However, there are some basic conditions for inline processing, in some cases the JIT compiler will not inline, such as virtual call, the method of the Il code length is too long (the current CLR is more than 32bytes code length is too long), there are complex control flow logic, exception handling and so on. These conditions are either simply not able to use inline (such as virtual attributes), or the cost of inline is too high, easily lead to the bloat of the code, or inline up time-consuming-has lost the meaning of inline, because. NET inline mechanism occurs in the JIT process. Using attributes has an individual uncomfortable place, such as it affects developer productivity, but does not have an impact on the efficiency of the code's operation.
distinguish between value types and reference types in use
This article discusses the tradeoff--of type design when designing a type as a struct or a class. Mr. Bill Wagner gave a principle. A value type is used to store data, and a reference type is used to define the behavior (value types store values and reference types define behavior) ".
How to judge the applicability of this principle, Bill Wagner also gave a way, that is, first of all answer the following questions:
1. Is the primary responsibility for this type used for data storage?
2. Are the public interfaces of this type a number of access attributes?
3. Are you sure that the type can never have subclasses?
4. Are you sure that the type can never have polymorphic behavior?
If the answer to all questions is yes, then the value type should be used. Such judgments do have good reasons to support them, but I personally think that "to answer the 4 questions" is not enough to constitute the full justification for the use of value types. Because in many project practices, I've found that the performance problems of value types are not trivial. There are two major performance problems with value types:
1. The box/unbox caused by the conversion of value type instances between the stack and the managed heap, and the garbage on the managed heap from which they were brought.
2. Value type By default is a value copy semantics, and if it is a larger value type, it can also cause performance problems when passing parameters and function return values.
On 1th, Bill Wagner refers to the seemingly correct judgment on the surface of the "reference type that will bring a burden to the garbage collector" in this article. But because of the effect of box/unbox, in some cases, the value type is more burdensome to the garbage collector. For example, some value types are placed in a collection and then frequently read and write to them. If this is the case, I think it would be a better idea to "abandon the structure and adopt the class". In fact, adding a value type that is used as a data store (such as System.Drawing.Point) to a collection (System.Collections.ArrayList) is a very common operation. However, the new generic technology introduced in C # 2.0 has greatly improved the box/unbox problem.
On the 2nd, Mr. Scott Meyers in the effective C + + 22nd "Try to use Pass-by-reference (transfer), less pass-by-value (value)" in the said more clearly. Although the struct type in C # has the default deep copy semantics, there is no call to the copy constructor. Also, there is no subclass of struct types, so there is no polymorphism in some way, and there is no cutting (slicing) effect that may occur when C + + objects are passed. However, the cost of a value copy is still not small. Especially in the case of a large value type, the problem is more serious. In fact, in the design guidelines for Class Library developers documentation for the. NET Framework, there is a principle (and some other concurrent principles) that describes when a struct type should be used Type instance data is less than 16 bytes in size. This document is primarily based on the operational efficiency level of the type, and Mr. Bill Wagner's terms are primarily considered from the type design level.
From the above two discussions, I am personally inclined to adopt a more conservative design strategy for structural types. And for the class can be actively and boldly used. Because the undesirable consequences of "the improper design of a structural type as a class" are much less than the undesirable consequences of "improper design of the class as a structural type". In the current experience, I even think that the only way to deal with unmanaged interop is to use the structure type for the best reason, and all the rest of the time "look before you leap." Of course, with the introduction of generic technology in C # 2.0, Box/unbox will no longer be a heavy burden, dealing with some very lightweight situations where the structure type still has its place.