Write high-quality code to improve the C # program's 157 Recommended Reading Notes

Source: Internet
Author: User

Suggestion 1: Correct string concatenation to avoid Boxing1, string str1 = "str1" + 9; 2, string str2 = "str2" + 9. toString (); from the IL code, it is learned that the first line of code will produce the packing behavior, while the second line of code 9. toString () is not packed. It directly operates the memory to convert int to string, which is more efficient than packing, when other value types are used to convert to strings for splicing, do not use "+". Instead, use the ToString () method provided by FCL to convert the data types and then splice them. In addition, because System. the immutable feature of String objects. New memory space must be allocated for the new object during String concatenation. Therefore, we recommend that you use StringBuilder when splicing a large number of strings. Recommendation 2: use the default transformation method 1. Use an internal method to use type conversion operators. Conversion operators are classified into two types: implicit conversion and explicit conversion (forced conversion) conversion operators are generally provided for primitive types. Int I = 0; float j = 0; j = I; // implicit conversion between int and float I = (int) j; // float to int must be explicitly converted to custom types. This type of conversion can be achieved through the overload conversion OPERATOR: copy the code class program {static void main (string [] args) {Ip address = "127.0.0.1"; // use the overload conversion operator of the ip class to implicitly convert the string to the Ip type Console. writeLine (ip. toString () ;}} public class Ip: Object {IPAddress value; // constructor public Ip (string ip) {value = IPAddress. parse (ip) ;}// overload conversion operator. The implicit keyword is used to declare implicit User-Defined conversion operators. Public static implicit operator Ip (string ip) {Ip iptemp = new Ip (ip); return iptemp;} // rewrite the base class ToString method public override string ToString () {return value. toString () ;}} copy code 2. Use the built-in Parse of the type in FCL. The type itself has some conversion methods. For example, the int itself provides the Parse and TryParse methods ...... 3. Use the method System provided by the help class. convert provides methods to Convert a primitive type to another primitive type, such as ToChar and ToBoolean. If a custom type is converted to any primitive type, you only need to customize the type to implement the IConvertible interface and implement the relevant conversion method. ps: the primitive type is the data type directly supported by the compiler, that is, directly mapped to the type in FCL, including sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, bool, decimal, object, string. 4. CLR supports up-and down-conversion between child classes and parent classes. implicit conversion is supported when child classes are converted to parent classes, when the parent class is converted to a subclass, it must be explicitly converted. For example, a dog (subclass) is an animal (parent class), but an animal is not necessarily a dog, it may also be a cat. Recommendation 3: differentiate forced transformation, as, is secondType = (SecondType) firstType; the above Code has a strong conversion type, which means one of the following two things; 1) firstType and SecondType depend on each other on the Conversion operator to convert the two types. 2) FirstType is the base class of SecondType. The first case is: there are conversion operators for FirstType and SecondType. Copy the code public class FirstType {public string Name {get; set ;}} public class SecondType {public string Name {get; set ;} // explicit and implicit are conversion operators. explicti: explicit conversion. implicit can be implicitly converted to public static explicit operator Sec. OndType (FirstType firstType) {SecondType secondType = new SecondType () {Name = firstType. name}; return secondType;} to copy the code, you must use strong conversion instead of the as operator. In this case, the code is compiled successfully, but an error is reported during running, the reason is that all the classes are inherited from the object, but the compiler will check whether o is of the SecondType type at runtime, thus bypassing the conversion operator. Therefore, we recommend that if there is an inheritance relationship between types, the as is preferred. Conversion between subclasses should provide conversion operators for forced conversion. The second case: FirstType is the base class of SecondType. In this case, either as or forced conversion can be used. In terms of efficiency and code robustness, we recommend that you use, because the as operator does not throw an exception, when the type does not match, the return value is null. Is and as: object o = new object (); if (o is SecondType) {secondType = (SecondType) o;} the actual efficiency of this Code is not high, the is Operator returns the boolean return value because of two type checks, but the detection does not convert, while the as operator performs conversion. If the conversion fails, null is returned. 4: tryParse is better than Parse to copy code // Parseint a = int. parse ("123"); // TryParseint x = 0; if (int. tryParse ("123", out x) {// The conversion is successful. x = 123} else {// The conversion fails. x = 0} copy the code. Needless to say, I believe that many people often use it, from. starting from NET2.0, FCL provides the TryParse method for the base element type to solve the performance consumption caused by exceptions triggered when Parse conversion fails. In terms of efficiency, if Parse and T If ryParse is successfully executed, the efficiency is in the same order of magnitude. Even in the experiment in the book, TryParse is higher than Parse. If both Parse and TryParse fail to be executed, the execution efficiency of Parse is much lower than that of TryParse. Suggestion 5: Use int? Make sure that the value type can also be null. during development, you may also encounter scenarios where the value type is insufficient. For example, if the data table field is set to the int type and the value type is allowed to be null, in C #, if null is assigned to an int type variable, an error is returned. starting from NET2.0, FCL provides a type Nullable that can be Null <T>. It is a struct: public struct Nullable <T> where T: Struct, but struct is a value type, it should not be left blank. I haven't explained it in depth in the book. A vague sentence or two is included. So I will continue to discuss it in depth. First, I will use Reflector to perform mscorlib. dll decompilation; copy the code public struct Nullable <T> where T: struct {private bool hasValue; internal T value; public Nullable (T value); publ Ic bool HasValue {get;} public T Value {get;} public T GetValueOrDefault (); public T GetValueOrDefault (T defaultValue); public override bool Equals (object other ); public override int GetHashCode (); public override string ToString (); public static implicit operator T? (T value); public static explicit operator T (T? Value);} I don't know why to copy the code. When I expand these methods, they are empty. However, I found that it has a heavy-load conversion operator, and implicit is an implicit conversion, explicit is an explicit conversion and then writes a small program. The Code is as follows: protected void Page_Load (object sender, EventArgs e) {Nullable <int> a = null ;} then, decompile the web application to view: protected void Page_Load (object sender, EventArgs e) {int? A = new int? () ;}It can be seen that Nullable <int> a = null; is finally initialized, and the value of the hasValue attribute should also be False; so, I guess, nullable <int> or int? ...... When an empty primitive type is set to null, Initialization is performed instead of being null as the reference type, and the value of the hasValue attribute is False. After the conjecture, I went to MSDN to search for it and got the verification: http://msdn.microsoft.com/zh-cn/library/ms131346 (v = vs.100 ). aspx Recommendation 6: differences between readonly and const. I plan to write a concise example instead of a book example, even if some friends who have been working for a few years, it may also be hard to tell the difference between const and readonly at once. They all have the same effect and indicate an immutable value. In fact, their differences are as follows: · const is the compile-time constant (the value determined during the compilation) · readonly is the run-time constant (determined only at the runtime). The following example creates a DEMO to illustrate: 1. Create a class library, create a Person class and set the following constants: copy the code namespace ClassLibrary {public class Person {public const int height = 100; public r Eadonly static int weight = 100;} copy code 2. Add a reference to the ClassLibrary class library in the main program. The output constant is protected void Page_Load (object sender, EventArgs e) {Response. write ("height:" + ClassLibrary. person. height); Response. write ("Weight:" + ClassLibrary. person. weight);} No doubt at this time, the output result is: height: 100 weight: 100, 3. Modify the height and weight constants in the Person class to: 170 ,, and compile the class library (Note: Only this class library is generated, instead of the main program). Then run the main program page and the output result is: Height: 100 weight: 170. The reason is, height is a const constant. During the first compilation, 100HardCode has been stored in the main program, However, the main program is not generated after the value is modified for the second time. Therefore, the value is the first time when the program runs again. Let's use ILDASM to check the compiled IL code. Recommendation 7: use 0 as the default value of enumeration. The enumerated types are byte, sbyte, short, ushort, int, uint, long, And ulong. Always use 0 as the default value of enumeration; I don't quite understand the example in this book. I understand it like this. If the following enumeration copies the code enum Week {Money = 1, Tuesday = 2, Wednesday = 3, thursday = 4, Friday = 5, Saturday = 6, Sunday = 7} copy the Code in case you accidentally write the code as static Week week; protected void Page_Load (object sender, EventArgs e) {Response. write (week);} If the output is 0, the eighth value is added. Therefore, we recommend that you use 0 as the default value for enumeration. Recommendation 8: Avoid providing explicit values for enumeration elements. "generally, there is no need to provide displayed values for enumeration elements." I think this suggestion is dispensable, in my personal habits, the author suggests that we add an element in the above enumeration. The Code is as follows: copy the code enum Week {Money = 1, Tuesday = 2, TempValue, wednesday = 3, Thursday = 4, Friday = 5, Saturday = 6, Sunday = 7} copy the code. What is the value of TempValue? Week week = Week. tempValue; Response. write (week); Response. write (week = Week. wednesday); the result of ValueTemp is: Wednesday True; if the element is not explicitly assigned a value, the compiler will + 1 for each element, that is, automatically + 1 on the basis of Tuesday = 2, and the final values of TempValue and Wednesday are both 3. Then, the author's intention is to simply not specify the value, because the compiler will automatically help us + 1, but my idea is that if we don't specify a value, when we come to see this enumeration next time, is it necessary to count the number of the elements to know the Value? In addition, if the enumeration has been modified, the Value may be lost due to accidental modification. System. flagsAttribute attribute when an enumeration specifies System. after the flagsattri attribute, it means that you can perform AND, OR, NOT, and xor bitwise operations on these values. This requires that the values of each element in the enumeration are two n power indexes, the purpose is that the value to be added by any element will not be the same as the value of any element in the current enumeration. This is rarely mentioned in the book, but I just mentioned a rough idea, so I made a DEMO for more in-depth research by referring to some materials. Copy the Code [Flags] enum Week {None = 0x0, Money = 0x1, Tuesday = 0x2, Wednesday = 0x4, Thursday = 0x8, friday = 0x10, Saturday = 0x20, Sunday = 0x40} protected void Page_Load (object sender, EventArgs e) {// use the "|" operation, combine various elements into Week week = Week. sunday | Week. tuesday | Week. thursday; Response. write (GetDayOfWeek (week);} private string GetDayOfWeek (Week week) {string temp = string. empty; foreach (Week w I N Enum. getValues (typeof (Week) {// use the "&" operation to split if (week & w)> 0) temp ++ = string. format ("{0} <br>", w. toString ();} return temp;} the output result of the copied code is: Tuesday Thursday Sunday. This design utilizes the "and" or "Operation of the binary number in the computer base, in this way, each element can be skillfully combined into a single data and finally split up. This design idea can be widely used in permission design and billing methods ...... And so on. Let me talk about the principle. First, let's look at the enumerated values defined by me. The corresponding binary numbers are 0001, 0010, 0100, and 1000 ...... For example, if the binary numbers of 0x1 and 0x8 are 0001 and 1000, the value after they are combined by the "|" operation is 1001, that is to say, when the GetDayOfWeek method is called, the parameter value is 1001, and then the result is larger than 0 when the enumeration is traversed and split by Monday: 1001 & 0001 = 0001, which meets the condition Tuesday: 1001 & 0010 = 0000 the result is equal to 0, Wednesday: 1001 & 0100 = 0000 the result is equal to 0, and Thursday: 1001 & 1000 = 1000 the result is greater than 0, this method can be used to identify the two elements that were originally combined. Recommendation 9: we have been familiar with the heavy-load conversion operators, so that we can convert objects of different types, such as IPAddress ip = "127.0.0.1, this makes the code more intuitive and concise. Similarly, for the following two sections of Code: (1) int total = x + y; (2) int total = int. add (x, y); of course we want to see the first, not the second, because most of us are familiar with the first syntax, when constructing our own types, we should consider whether operators can be overloaded. Copy the code class Salary {public int RMB {get; set;} public static Salary operator + (Salary s1, Salary s2) {s2. RMB + = s1. RMB; return s2 ;}} after the code is reloaded, you can use it in this way, which is more convenient. Salary s1 = new Salary () {RMB = 10}; Salary s2 = new Salary () {RMB = 20}; Salary s3 = s1 + s2; Recommendation 10: when creating an object, you need to consider whether the comparator has an object and there will be a comparison. During the next year, your mom will compare you with other children, you can implement the IComparable interface to implement the comparative sorting function. Let's first create a basic class to see how the comparator is implemented step by step; class Salary {public string Name {get; set ;} public int BaseSalary {get; set;} public int Bonus {get; set ;}} is compared and sorted even if ArrayList has the sort () sorting method? Is it really so beautiful? Copy the code ArrayList companySalary = new ArrayList (); companySalary. add (new Salary () {Name = "A", BaseSalary = 2000}); companySalary. add (new Salary () {Name = "B", BaseSalary = 1000}); companySalary. add (new Salary () {Name = "C", BaseSalary = 3000}); companySalary. sort (); // Sort foreach (Salary item in companySalary) {Response. write (item. name + ":" + item. baseSalary);} the reality of copying code is so miserable, because there are many fields in the object class, the compiler will not be smart enough to know where you want to use Fields used for sorting and comparison. So, we must implement the IComparable interface for the Salary class, and implement the interface member CompareTo (object obj) to copy the code class Salary: IComparable {public string Name {get; set ;} public int BaseSalary {get; set;} public int Bonus {get; set;} // implement the CompareTo method of the IComparable interface. The principle of the comparator is public int CompareTo (object obj) {Salary staff = obj as Salary; if (BaseSalary> staff. baseSalary) {return 1; // if it is large, return 1} else if (BaseSalary = staff. baseSalary) {Return 0;} else {return-1; // if it is small, return 1 }}copy the Code where the code is called without modification. The program runs again, the running result is: B: 1000 A: 2000 C: 3000OK. Let's go deeper. If this month's settlement is not sorted by BaseSalary, but by Bonus, what should we do? Of course, it is certainly possible to re-Modify the members of The CompareTo interface in the Salary class. However, the clever method is to customize the comparator interface IComparer (Note: The Implementation Interface Name Is IComparable, the custom comparator interface is IComparer. Copy the code class BonusComparer: IComparer {public int Compare (object x, object y) {Salary s1 = x as Salary; salary s2 = x as Salary; return s1.Bonus. compareTo (s2.Bonus); // In fact, The CompareTo method of the internal field can also be used in the previous example. // However, because the internal principle of the comparator is demonstrated, several if statements are written.} The Sort method of the copied code accepts a class object that implements the IComparer interface as a parameter. Therefore, we can transmit the parameter in this way // provide a non-default comparator BonusComparercompanySalary. sort (new BonusComparer (); the content of the comparator should end here. The next step is to consider performance issues during comparison. As you can imagine, if tens of thousands of data in a set needs to be compared, and in the above example, the type conversion Salary s1 = x as Salary is used; this is very performance-consuming, the emergence of generics can effectively avoid the problem of type conversion: 1. ArrayList can be replaced by List <T>. 2. Use IComparable <T> and IComparer <T> to replace Just Look Like That to copy the code class Salary: IComparable <Salary> {public string Name {get; set;} public int BaseSalary {get; set;} public int Bonus {get; set;} public int CompareTo (Salary staff) {return BaseSalary. compareTo (staff. baseSalary) ;}} class BonusComparer: IComparer <Salary> {public int Compare (Salary x, Salary y) {return x. bonus. compareTo (y. bonus );}}

Related Article

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.