157 suggestions for writing high-quality code to improve C # programs [Give priority to generics, avoid declaring static members in generics, and set constraints for generic parameters]

Source: Internet
Author: User

Preface

Generic is not a feature that comes with C # From the very beginning, but a new feature that is implemented after FCL2.0. Based on generics, We Can parameterize types for code reuse in a larger scope. At the same time, it reduces the transformation of generic classes and generic methods and ensures type security. The delegate itself is a reference type, which saves the reference of objects in the managed heap, but this reference is special, and it is a reference to the method. The event itself is also a delegate group, and C # provides a keyword event to differentiate events. Once we start to write a slightly Complex C # code, it is certainly inseparable from generics, delegation, and events. This chapter describes these three aspects.

Here I also have a simple understanding of generic here I have a simple understanding of http://www.cnblogs.com/aehyok/p/3384637.html C # Generic (security, set, method, constraints, inheritance)

This article has been updated to http://www.cnblogs.com/aehyok/p/3624579.html. This article mainly records the following content:

Recommendation 32: always give priority to generic

Suggestion 33. Avoid declaring static members in a generic type.

Recommendation 34. Set constraints for generic parameters

Recommendation 32: always give priority to generic

Generics have many advantages. both generic and generic methods have the reusability, type security, and high efficiency features at the same time, this is not possible for non-generic and non-generic methods. In this article, we recommend that you analyze the reusability, type security, and efficiency of generic encoding.

I. reusability. For example, you can simply design a collection class.

Public class MyList {int [] items; public int this [int I] {get {return items [I];} set {this. items [I] = value ;}} public int Count {get {return items. length ;}}/// omit some other methods}

This type only supports integer types. If you want the type to support strings, you can redesign a class. However, the attributes and methods of these two types are very similar. If there is a method that allows the type to receive a common data type, the code can be reused, at the same time, only one type is enough. This is done by generics.

Public class MyList <T> {T [] items; public T this [int I] {get {return items [I];} set {this. items [I] = value ;}} public int Count {get {return items. length ;}}// omit other methods}

T can be understood as a placeholder. In the IL code generated by C # Generic compilation, T is a placeholder role. During the runtime, even if the compiler (JIT) replaces T with the T type entered in the actual code, that is, in the local code generated by JIT, the actual data type is used. We can regard MyList <int> and MyList <string> as two completely different types. However, this is only for local code. For actual C # code, it only has one type, that is, the generic type MyList <T>.

The above demonstrates the advantages of generics from the perspective of code reusability. From the perspective of Type MyList <T>, if code reuse is not required for generics, another method is to design the MyList encoding from the object perspective. In the C # world, all types (including value type and reference type) are inherited from the object. To make MyList generic enough, you need to make MyList encoded for the object. The Code is as follows:

Public class MyList {object [] items; public object this [int I] {get {return items [I];} set {this. items [I] = value ;}} public int Count {get {return items. length ;}}/// omit some other methods}

This will allow the following code to be compiled

            MyList list = new MyList();            list[0] = 123;            list[1] = "123";

The problem caused by the above two lines of code is non-"type security". The problem has been discussed in detail in the suggestion 20 http://www.cnblogs.com/aehyok/p/3641896.html. To ensure type security, the program can filter out some bugs during compilation, at the same time, the Code can also avoid the efficiency loss caused by "transforming to object type" or "transforming from object to actual type. Especially when the involved operation type is value type, it also causes performance loss of packing and unpacking.

For example

list[1] = 123;

It will bring about a packing operation, because it is converted to an object first, and then stored in the items object array.

Generics bring about revolutionary changes to C #. Many of the functions after FCL are implemented with generics, such as LINQ. With the help of generics and extension methods, LINQ effectively enriches the query functions of the Set, avoids code explosion and improves the operation performance. When designing our own types, we should fully consider the advantages of generics and turn our own types into generic classes.

 

Suggestion 33. Avoid declaring static members in a generic type.

In the previous suggestion, we have explained that MyList <int> and MyList <string> should be treated as two completely different types. Therefore, static members in MyList <T> should not be considered as members in both MyList <int> and MyList <string>.

For a non-generic type, the following code is well understood:

    public class MyList    {        public static int Count { get; set; }        public MyList()        {            Count++;        }    }    class Program    {        static void Main(string[] args)        {            MyList myList1 = new MyList();            MyList mylist2 = new MyList();            Console.WriteLine(MyList.Count);            Console.ReadLine();        }    }

The result is 2.

If you replace MyList with a generic type, what will be output in the following code?

    public class MyList<T>    {        public static int Count { get; set; }        public MyList()        {            Count++;        }    }    class Program    {        static void Main(string[] args)        {            MyList<int> myList1 = new MyList<int>();            MyList<int> mylist2 = new MyList<int>();            MyList<string> mylist3 = new MyList<string>();            Console.WriteLine(MyList<int>.Count);            Console.WriteLine(MyList<string>.Count);            Console.ReadLine();        }    }

Code output is

Public class MyList {public static int Count {get; set;} public static int Func <T> () {return Count ++ ;}} class Program {static void Main (string [] args) {Console. writeLine (MyList. func <int> (); Console. writeLine (MyList. func <int> (); Console. writeLine (MyList. func <string> (); Console. readLine ();}}

The output result is

Recommendation 34. Set constraints for generic parameters

The word "constraint" May cause ambiguity. Some people may think that the restriction on generic parameter settings is to restrict the use of parameters. The actual situation is the opposite. Generic parameters without constraints have limited functions, but "constraints" Give generic parameters more behaviors and attributes.

Public class Salary {// <summary> /// Name // </summary> public string Name {get; set ;} /// <summary> /// basic salary /// </summary> public int BaseSalary {get; set ;} /// <summary> /// bonus /// </summary> public int Bouns {get; set ;}} public class SalaryComputer {public int Compare <T> (T t1, T t2) {return 0 ;}}

 

Looking at the object class defined above, we can find that the parameter t1 or t2 of the Compare <T> method only has the attributes and behavior of the object, so it is almost impossible to perform any operation on them in the method. However, after adding constraints, we will find that the t1 or t2 parameter becomes a useful object. Because the corresponding type is specified for it, t1 and t2 are now a Salary. Inside the method, it has the attributes BaseSalary and Bonus. The Code is as follows:

    public class SalaryComputer    {        public int Compare<T>(T t1, T t2) where T:Salary        {            if (t1.BaseSalary > t2.BaseSalary)            {                return 1;            }            else if (t1.BaseSalary == t2.BaseSalary)            {                return 0;            }            else            {                return -1;            }        }    }

Which constraints can be specified for generic parameters?

1. The specified parameter is of the value type (except Nullable) and can be in the following format:

        public void Method1<T>(T t) where T : struct        {                     }

2. The specified parameter is of reference type and can take the following form:

        public void Method1<T>(T t) where T : class        {        }        public void Method1<T>(T t) where T : Salary        {        }

Note that objects cannot be used as constraints.

3. If the specified parameter has a public constructor without parameters, it can take the following form:

        public void Method2<T>(T t) where T : new()        {         }

Note that currently, CLR only supports the construction method constraints without parameters.

4. The specified parameter must be the specified base class or be derived from the specified base class.

5. The specified parameter must be the specified interface or implement the specified interface.

6. The type parameter provided by the specified T must be a parameter provided by the U, or derived from the parameter provided by the U.

    public class Sample<U>    {        public void Method1<T>(T t) where T : U        {                     }    }

7. You can set multiple constraints for parameters of the same type, and the constraint itself can be a generic type.

In programming, we should always consider setting constraints for generic parameters. As mentioned at the beginning of this suggestion, constraints make generics a real "object ", let it have the behavior and attributes we want, not just an object.

 

Tips for English

1. Where is the tourist information? -- Where is the tourism Consulting Center?

2. Can you recommend a hotel which is not too expensive? -- Can I suggest a cheaper hotel?

3. Is there an airport bus to the city? -- Is there an airport bus in the city?

4. Is there a hotel which costs under 50 dollars a night? -- Is there any hotel that spends less than $50 per night?

5. Where is the bus stop (taxi stand )? -- Where is the bus stop card (taxi greeting station?

6. Could you recommend a hotel in the city center? -- Can I suggest a hotel in the city center?

7. Where can I get the limousine for Hilton Hotel? -- Where can I take a shuttle bus from the Hilton hotel?

8. I 'd like to stay at a hotel near the station. -- I want to stay in a hotel near the station (beach.

Author: aehyok

Source: http://www.cnblogs.com/aehyok/

Thank you for reading this article. If you are interested in the content described in my blog, please make a suggestion. Thank you for your support:-O.

 

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.