Valid tive C # Chapter1-Language Elements

Source: Internet
Author: User
Tags types of functions

Effectivec # describes some tips and experiences on using C # language. this series of articles is memorandum and some of your own opinions. programmers like this kind of problem most. Welcome to discuss it ~


Menu

Item 1 replace public member variables with properties

Item 2 takes precedence over readonly instead of const

Item 3 replaces the conversion operator with is/As for object type conversion

Item 4 is replaced by conditionalattribute # If

Item 5 always provides the tostring () method

Item 6 Differences between value types and referance types

Item 7 perfer immutable atomic Value Type

Item 8 ensures that 0 (default object, default (t) is a valid state (defined State)

Item 9 Methods for understanding the Ratio Relationship: referanceequals (), static equals (), instance equals (), and operator =

Item 10 understands the traps in gethashcode ()

Foreach is preferred for item 11

Item 1 replace public member variables with properties

This is the initial tangle of C ++ to C # programmers.


1. If it is public datamember, this is definitely incorrect. Whether it is C ++ or C #, it must be encapsulated.

Specifically, in C #, if datamember is used, it will lead to a change in the variable (for example, the default value) during cross-Assembly use. All the assemblies that use the variable have to be re-compiled.
This will become a disaster in Multi-DLL projects.

2. porperty and indexer are the concepts and language feature types in C #.

So why can't c ++ access methods be used? Since access methods is the stuff in C ++, using property to control the Member's issue will get some programming convenience provided by C, for example, a [attribute] can be directly applied to a property, and access methods must be used to process get and set separately, which is more complicated to implement;
Many other language features are also based on "property". This language property can be used to get type differences in reflection-related encoding activities, while access methods is the encoding style, C # is not correct. It is directly supported in language.

3. No difference in performance

JIT implements inline property accessor for property, so the performance is equivalent to datamember.

Summary:

Attribute is always used to provide the capability of Data profiling.(Valuetype may have special cases, such as vector3 and matrix44 );
Indexer is always used to provide data queue or location capabilities.
All data members are private
(Or protected, personal opinion );
Neither property nor indexer can throw exceptions;


Item 2 takes precedence over readonly instead of const

1. C # has two versions of constants: const and readonly)

When const is compiled into Il, it will directly interpret the constant as the literal value, while readonly will interpret it as a reference.

2. const is the most efficient, but there are potential risks

Both of them have value. Const has no performance overhead and is the most efficient because it directly uses a literal value constant to generate il code.
Consider the following potential risks:
The a version number of the Assembly is published. There is a const value of 4 in it, because it is datamember (reason 1 for listing Item1 ), all the code used by the client using this assembly is compiled into 4.
Several weeks later, the Assembly is updated to Version B, and the value of const is changed to 5. no matter where the const is used in the related collection that has not been compiled again, the value is 4. (raise your hand if you are in trouble)

3. readonly has a certain degree of flexibility, but also has a small amount of performance overhead.

Readonly is consistent with const in terms of syntax features during the compilation period, and can avoid potential risks arising from const during the execution period. All usage is to remember the specified variable of the specified Assembly, rather than directly writing it into the literal value.
Naturally, such a reference will bring about performance overhead, but it is just an inline overhead.
In my opinion, readonly applies to const, just like property on data member.
Summary: Const is used only when performance is particularly emphasized, and readonly is used in any other scenarios. Const constants must be used to ensure that the version number is not changed when the program continuously updates the version number. Otherwise, readonly is used.

Item3 uses is/as to replace the conversion operator for object type conversion. This is similar to the clause in C ++ that uses xxxcast to replace forced conversion. Only when the forced conversion in C # fails, an exception is thrown, not as quietly as C ++. We know that the object-oriented language should not be directly transferred, so there is nothing to discuss about this provision.
Summary: Always use as/is for type conversion

Item 4 is replaced by conditionalattribute # If well, this is a novelty that C ++ programmers have never seen before
[Conditional("DEBUG")]void fun(){        // do something in debug model}

1. This function can be called wherever it is. During release compilation, this function and its calling code are like they do not exist at all.This syntax feature reduces the workload of compiling code that requires Conditional compilation to some extent. 2. Except for debug, Conditional compilation variables such as trace that have been built into ide support arbitrary Conditional compilation variables. 3. [conditional (A), conditional (B)], which is equal to # If a | B. To express a and B, it must be pre-defined.# If a & B # define C # endif 4. Only functions are supported.
Summary:In fact, it cannot completely replace # If.

Item 5 always provides the tostring () method Summary:You don't need to list the reasons. Do you have to write less code for dump object content? In the world of C #, every class should have tostring. Let's work together to make this beautiful thing continue! Some classes that need to support specific formats must implement the iformattable interface.

Item 6 understands the difference between value types and referance types. This is a long term and there are too many articles to explain the difference between them. Here I will list some related knowledge points. 1. Pass values and references 2. C # is not often referenced. It is a constant function.
3. Boxing and unboxing) 4. valuetypes does not support implementation inheritance, but supports interface inheritance. Using valuetype through the interface causes boxing operations. 5. Many C # default implementations are based on objects. These implementations will lead to the boxing operation of valuetype.
Item 7 perfer immutable atomic Value Type 1. Immutable featuresThe atomic valuetype of the unchangeable feature. Well, to be honest, I don't think valuetype must be immutable, but the immutable feature is very practical. Strcut A {public int X {Get; set;} is not immutable, because when an object holds this type of instance, for example, G. A = new A (); we can use g. a. X = 3 to change the internal status of. To make a variable, you need to remove all the set methods. This class is the immutable class. But what is the use of a class that cannot change its internal state? It will be explained later.
2. Atomic featuresConsider another situation:
strcut Address{public int ZipCode{get;set;}public string CityName{get;set;}}


This is an address class, but there is a problem, that is, we agree to the user's error from the open interface: only change zipcode without changing cityname, this will cause the zip code and city to be unable to match! This class is not atomic.
In order to maintain the uniformity of the internal data of the object, it is necessary to provide some specific atomic-level question interfaces. For example, address can provide a special function to maintain its atomic characteristics.
struct Address{private int _zipCode;private string _cityName;public int ZipCode{get { return _zipCode; }}public string CityName{get { return _cityName; }}public Address(int zipCode, string cityName){_zipCode = zipCode;_cityName = cityName;}public void Modify(int zipCode, string cityName){_zipCode = zipCode;_cityName = cityName;}}


Although we will not encounter an error when using the address, this new atomic address is not immutable because we can change its internal status. Now we change it to immutable:
public Address Modify(int zipCode, string cityName){return new Address(zipCode, cityName);}

We can see that we only changed a function. Modify no longer changes the internal properties of the object, but creates a new address instance and returns it. This class is the valuetype with immutable and atomic attributes.
After understanding the concepts of immutable and atomic, we can make some extension discussions: 1. immutable or atomic is not necessarily Value TypeString is an immutable referance type, so it is used like the valuetype of built-in, just like an int. Atomic does not matter. 2. If the class holds the referancetype datamember, it is very difficult (or can be done) to maintain its immutable attribute, mainly because of its reference transfer feature.This is also why we recommend that you use valuetype to implement the immutable data structure: immutable objects do not change the internal state of data, while valuetype transfers values when assigning values without changing the internal state of the owner. 3. the immutable attribute is suitable for hashcode and other things.In fact, gethashcode uses the gethashcode of the first datamember of the object as the hash value of the entire object by default.
Item 8 ensures that 0 (default object, default (t) is a valid state (defined State) C # And C ++ are somewhat different during object initialization: whether it is debug or release, C # Always initializes various variables to 0 --- valuetype is 0, and reftype is null. Summary: 1. handle such a thing in the code 2. Enum must include 0 as a valid value-even if it is meaningless, it also indicates that we have considered an Enum object being initialized to 0 by default.
Item 9 Methods for understanding the Ratio Relationship: referanceequals (), static equals (), instance equals (), and operator =
public static bool ReferanceEquals(object left,object right)public static bool Equals(object left,object right)public virtual bool Equals(object right)public static bool operator==(T left, T right)

So far is better than the attention function... people who just came from C ++ are expected to be dizzy at once. The following four sections explain the characteristics and differences of the above four types of functions. 1. referancequals is used to determine whether the two references are equal to each other. The programmer will never change this function by himself.In C #, Named handler and an unspecified objectThis concept is equivalent to the same variable and variable value. This function is used to check whether the reference indicated by handler is consistent. This function cannot act on valuetype or enumtype, because it only checks ReferenceFor the value type, calling this function will lead to boxing. Therefore, two objects are encapsulated. It must be different. The same is true for enum. 2. Static bool equals is implemented by default, and left. Equals (right) is called by default. The programmer will never change this function by himself.This is a default mechanism. When the ratio is equal Polymorphism + system. object is the base class of all typesTo check whether two objects are equal. Token exams are actually available
public static bool Equals(object left,object right){if(left == right)return true;if(left==null || right == null)return false;return left.Equals(right);}

We can see that this function calls = first and then instance. Equals. It is very complete, right? There are traps here. This function cannot be reloaded, but it uses the object as the number of objects. This means that when Enum or valuetype is used, boxing operations will occur, which leads to performance overhead. 3. For valuetype, this function always needs to be reloaded. For reftype, the default behavior is not reloaded unless it is changed. The default behavior of reftype is only referenced by limit.If the valuetype equals is not used, it works right. However, because of its boxing operation, C # uses reflection to make the random valuetype datamember correctly obtain the ratio, it is 1000000 times slower than boxing! The significance of overloading is to exclude unnecessary reflection operations: We can directly infer whether the right type is better than others. For reftype, unless we want to customize its comparison rules, we can all rely on C #'s own default implementation. There is no boxing or reflection here. Reftype only deduce whether the reference is equal, not whether the content is equal. 4. Operator = (t, t) This is prepared to eliminate boxing and cast. In most cases, valuetype only understands to overload this operator. Reftype should always use equals for comparison.Reftype content ratio, and finally all need to compare the value type on the valuetype. We can call the valuetype instance. equals (with performance overhead and at least boxing) can also call its operator = (), which can directly give specific types of comparison, directly eliminate the possibility of various boxing and reflection. 5. Whether reftype is reloaded 3 and 4. You need to check whether the ref value is equal in details. In most cases, you only need to implement the instance. equals, 4 is implemented only when there is a need for syntactic sugar.
Item 10 understands the traps in gethashcode ()After understanding the concept of immutable, this entry is very easy to understand: assuming that the datamember as hash can be changed and changed, there will be no stable results. Another is that for an object, assuming that a non-readonly data member is used as the basis for its hash computing, the object is stored in a hash-based container after the calculation is complete, if the hash member variable changes again, it will no longer be retrieved from the container through the hash value. C # You are not prohibited from doing so, so the risks must be borne by yourself.
Summary: 1. If valuetype's gethashcode () is to work normally, you must make your first data member readonly immutable type object, otherwise, the result may not be correct. Assume that you can take the risk. 2. Assume that you need to write the return value of hashcode. In most cases, use the gethashcode () value of all immutable members for XOR. The result value is used as the hash value of the current type.
Foreach is preferred for item 11 1. the compiler will take the initiative to make the best code translation for foreach.For example, the data structure of the array type, foreach is equivalent to for (INT I = 0 ....) for associated containers, using (var e = container. getenumartor ()){...} such a structure. Users do not need to care about implementation details. 2. Using the intermediate variable to remember the Count structure cannot compare with foreach.Since foreach has been optimized at the Il level, it is faster than manual code including intermediate computing.
Conclusion: Use foreach to implement a loop! (Personal experience, because of the bug of mono. dll used by unity3d, you must manually implement the while (E. movenext () {...} structure to avoid meaningless GC alloc)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.