Struct cannot be a base class. So, Struct types cannot abstract and are always implicitly sealed. Abstract and sealed modifiers are not allowed and struct member cannot be protected or protected internals. Function members in a struct cannot be abstract or virtual, and the override modifier is allowed only to the override methods inherited from System. Struct does not allow the instance field declarations to include variable initializers. But, static fields of a struct are allowed to include variable initializers.
A struct can implement interfaces. A struct can be used as a nullable type and can be assigned a null value. If the consumer wants to change the value, they can create a new object based on the values of the old one, with the changes they want, or they can call a method which will do the same.
This forces them to treat a single instance of your struct as one conceptual "value", indivisible and distinct from but possibly equatable to all others. For a good example, look at the DateTime type. You cannot assign any of the fields of a DateTime instance directly; you must either create a new one, or call a method on the existing one which will produce a new instance.
This is because a date and time are a "value", like the number 5, and a change to the number 5 results in a new value that is not 5. DateTimes work the same way; does not "become" if you add a minute, you instead get a new value that is distinct from If this is a logical state of affairs for your type good conceptual examples that aren't built in to.
NET are Money, Distance, Weight, and other quantities of a UOM where operations must take all parts of the value into account , then use a struct and design it accordingly. In most other cases where the sub-items of an object should be independently mutable, use a class. The answer: "Use a struct for pure data constructs, and a class for objects with operations" is definitely wrong IMO. If a struct holds a large number of properties then a class is nearly always more appropriate.
Microsoft often says, from an efficiency point of view, if your type is larger than 16 bytes it should be a class. The most important difference between a class and a struct is what happens in the following situation:. What should be the effect of the last statement on thing1. If Thing a struct, and somePropertyOrField is an exposed public field, the objects thing1 and thing2 will be "detached" from each other, so the latter statement will not affect thing1.
If Thing is a class, then thing1 and thing2 will be attached to each other, and so the latter statement will write thing1. One should use a struct in cases where the former semantics would make more sense, and should use a class in cases where the latter semantics would make more sense. Note that while some people advise that a desire to make something mutable is an argument in favor of it being the class, I would suggest the reverse is true: if something which exists for the purpose of holding some data is going to be mutable, and if it will not be obvious whether instances are attached to anything, the thing should be a struct likely with exposed fields so as to make clear that instances are not attached to anything else.
Will the second statement alter the information stored in myPeople? If Person is an exposed-field struct, it won't, and the fact that it won't will be an obvious consequence of its being an exposed-field struct ; if Person is a struct and one wishes to update myPeople , one would clearly have to do something like myPeople.
UpdatePerson "", somePerson. If Person is a class, however, it may be much harder to determine whether the above code would never update the contents of MyPeople , always update it, or sometimes update it. With regard to the notion that structs should be "immutable", I disagree in general.
There are valid usage cases for "immutable" structs where invariants are enforced in a constructor but requiring that an entire struct must be rewritten any time any part of it changes is awkward, wasteful, and more apt to cause bugs than would simply exposing fields directly.
The effect of the following should be pretty clear:. Note that nothing in the above code knows or cares about any fields in PhoneNumber other than AreaCode and Exchange. If PhoneNumber were a so-called "immutable" struct, it would be necessary either that it provide a withXX method for each field, which would return a new struct instance which held the passed-in value in the indicated field, or else it would be necessary for code like the above to know about every field in the struct.
Not exactly appealing. In the former scenario, the object's IDENTITY will be immutable; in the second, the class of the nested object may not enforce immutability, but the struct holding the reference will.
I tend to use structs only when there is one method is needed thus making a class seems too "heavy". Thus sometimes I treat structs as lightweight objects.
BEWARE: this does not always work and is not always the best thing to do, so it really depends on the situation! This makes it obvious that all that structure is is a container for data.
If your structure has operations that modify the structure in any more complex way, use a class. A class also can interact with other classes via arguments to methods.
Think of it as the difference between a brick and an airplane. A brick is a struct; it has lenght, width and height. What matters is its interface. So a class rises the level of abstraction much more than a struct does, because it hides an implementation behind an interface that describes what this class can do. Another thing that a class can do is implementing invariants. An invariant is a property that must hold true all the time in a class from the perspective of the client of that class.
For example, say in a string, you have a buffer than contains the characters populating the string, and also a size in the string.
And from the perspective of the user of that string, you want that the size corresponds to the actual number of characters in the string.
The contract of a class is the constructor puts those invariant in place, and all the methods assume that those invariants are verified. But in a distant future we may have more than that, with the metaclasses proposal. In addition, in a majority of cases value type arrays exhibit much better locality of reference. The next difference is related to memory usage.
Value types get boxed when cast to a reference type or one of the interfaces they implement. They get unboxed when cast back to the value type. Because boxes are objects that are allocated on the heap and are garbage-collected, too much boxing and unboxing can have a negative impact on the heap, the garbage collector, and ultimately the performance of the application.
In contrast, no such boxing occurs as reference types are cast. For more information, see Boxing and Unboxing. Next, reference type assignments copy the reference, whereas value type assignments copy the entire value. Therefore, assignments of large reference types are cheaper than assignments of large value types.
0コメント