C # Summary of several frequent mistakes

Source: Internet
Author: User

In our ordinary programming, after a long time, sometimes we will form a habitual way of thinking, forming an inherent programming style, but in some places we need to consider it, even a small mistake may lead to a high price. You must learn to sum up and learn from the mistakes. Try not to make the same mistake, pay attention to the beauty of programming, and the elegance of code, summarize several common mistakes.

1. in C # programming, the struct type is the most error-prone and costly. in net framwork, the string is a quite special reference type. in this province, the string is a non-inherited sealing class, but it has the characteristics of the value type application, however, it is stored in the CLR memory on the managed heap. That is to say, each time we define a string type, one end of the memory is opened in the heap memory, when a string is modified, it creates a new memory. Note that the memory here is not continuous. Instead, it pieces the string by modifying the stack address reference, it does not change the address of the source string in the memory, so some programmers always like to format the string using this method:

string  SelectText="select * from "+TableName+" where UserName='"+Name+"'"; 

The above Code uses the String concatenation method. Because multiple concatenation is used, two unnecessary junk copies of strings are created in the memory.

In fact, in C #, we have provided stringbuilder and string. fromat to solve this problem, although they can implement the same function, but they have a qualitative change, stringbuilder opened a continuous memory in the memory, when adding a new string, it will store characters continuously in the same heap memory that the stack points to, which forms a performance improvement. So we changed the above Code:

string SelectText=string.Format("select  *  from {0} where UserName={1}",TableName,Name); 

2. Most developers do not know the built-in methods for verifying data types, such as system. int32, so many people implement it by themselves. In fact, this is inappropriate, because these basic types all have their own inherent type verification methods, the following code verifies whether a string is a numerical value:

public bool CheckIfNumeric(string value)  {      bool IsNumeric=true;      try      {             int i=Convert.ToInt32(value);       }       catch(FormatException excepiton)       {             IsNumeric=false;       }       return IsNumeric;  } 

Although the try catch statement is used, this is not the best practice. A better method is to use Int. tryparse below;

int output=0;  bool IsNumeric=int.TryParse(value,out output); 

Int. tryparse is a faster and more concise method.

3. manually release the memory using the idisposable Interface

In. in the. NET Framework, object processing and usage are equally important. The ideal method is to release the memory by implementing the dispose method in the idisposable interface in the class when the object is used up. the garbage collection mechanism (GC) provided by net itself provides such a function. When we instantiate class objects, the dispose method will be called in the class's destructor, GC automatically checks the object usage and releases the memory when the memory is full at all levels. However, to run on an unmanaged platform, we need to manually release the memory, for example, the common sqlconnection object has the following creation, use, and processing methods:

public void  DALOneMethod()  {      SqlConnection  connection=null;      try      {            connection =new SqlConnection("。。。。。。。。。。。");            connection.Open();            //sqlcommand。。run        }       catch(Exception exception)       {               // manager exception       }       finally      {              connection.Close();              connection.Disopse();       }  } 

The above code is the code that most programmers will encounter. At first glance, there is no problem. Connection processing is explicitly called in the last Code. However, if an exception occurs, the catch code block will be executed, then execute the last code block to process the connection. Therefore, before the last code block is executed, the connection will remain in the memory. Most of the errors will be recorded here, which generally involves Io operations, if the latency is long, the connection will stay in the memory for a long time. One principle is to release resources when the object is no longer used.

It is better to use the program logic domain to solve this problem:

public void  DALOneMethod()  {      using(SqlConnction  connection=new SqlConnection("。。。。。。。"))       {           connction.Open();        // do SUAD       }  } 

When the using code is fast, the dispose () method on the object will be called when the logic domain is launched. This ensures that the sqlconnection resource processing is released as soon as possible, of course, this method also applies to classes that implement the idisposable interface. At that time, I did not recommend this method. I can manually release it if I am very confident, but I still want to call it. the net system is released because the destructor of the class itself implements this method. When we rewrite the method by ourselves, the system will mistakenly think that you have defined the method and postpone the release of resources, if you are interested, you can study the essence of GC operation. If you can release the memory in the first generation, and if we rewrite the dispose method, it is obviously not desirable to release it in the second generation memory heap.

4. Learn to manage public variables rationally. We often abuse public variables in the system and fail to encapsulate them properly.

Static void main (string [] ARGs) {myaccount account Account = new myaccount (); // you cannot change the fields in the account, but the account is missing. accountnumber = "ddddddddd"; console. readkey () ;}public class myaccount {Public String accountnumber; Public myacctount () {accountnumber = "ssssssssssssss ";}}

In the above myaccount class, an accountnumber public variable is generated. Ideally, accountnumber should be read-only and cannot be modified by the outside world. However, the myaccount class does not have any control over it.

Declaring public practices should use attributes, such:

public  class  MyAccount  {     private stirng _accountNumber;     public  string AccountNumber     {          get {  return  _accountNumber;  }     }     public  MyAccount()     {            _accountNumber="dddddddd";     }  } 

Here we encapsulate the accountnumber public variable, which is read-only and cannot be modified by the caller class.

5. nested Exception Handling. Some developers prefer to add the nested method to the end of the method, as shown in figure

public class NestedExceptionHandling    {        public void MainMethod()        {            try           {                //some implementation                ChildMethod1();            }            catch (Exception exception)            {                //Handle exception            }        }            private void ChildMethod1()        {            try           {                //some implementation                ChildMethod2();            }            catch (Exception exception)            {                //Handle exception             throw;                }        }            private void ChildMethod2()        {            try           {                //some implementation            }            catch (Exception exception)            {                //Handle exception                throw;            }        }    } 

If the same exception is processed multiple times, the performance overhead will increase.

Our solution is to separate the exception handling methods, such:

public class NestedExceptionHandling    {        public void MainMethod()        {            try           {                //some implementation                ChildMethod1();            }            catch(Exception exception)            {                //Handle exception            }        }            private void ChildMethod1()        {            //some implementation            ChildMethod2();        }            private void ChildMethod2()        {            //some implementation        }    } 

6. Use dataset and datareader to mix large data volumes. When the data volume in a single table is large, it is unwise to use dataset to store data volumes in the form of able memory, one-time data is dragged into the memory. when the data is large, this method consumes much memory. Compared with dataser, datareader is much more elegant. It reads a piece of data each time, the Round-Robin call mechanism also has its drawbacks, that is, relatively long connections, but this is advantageous for memory consumption. Of course, dataset also has its own advantages in most application scenarios, in terms of full decoupling, one-time operation, and domain model operation, the two are used in different scenarios. Here we will only mention the differences based on the scenario analysis.

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.