10 C # errors that C programmers are easy to commit
We know that the syntax of C # is very similar to C , realizing the transition from C to C #, its difficulty is not in the language itself, but is familiar with .NET's manageable environment and to understand the .NET framework. Although C # and C changes in grammar, it is hard to have any effect on us, but some changes are enough to make some careful C programmers always remember in mind. In this article we will discuss ten errors that C programmers are most probably. Trap 1: There is no clear end method to completely say that for most C programmers, the difference between C # and C is debris collection. This also means that the programmer does not need to worry about memory leaks and ensure that all unwitched pointers are removed. But we can never accurately control the process of killing useless objects. In fact, there is no clear destructor in C #. If you use non-manageable resources, you must be explicitly released without using these resources. The implicit control of the resource is provided by the Finalize method (also known as Finalizer). When the object is destroyed, it will capture the resource occupied by the debris collection program. Finalizer should only release non-manageable resources occupied by the destroyed object, and should not involve other objects. If you only use a manageable resource in the program, you don't need to perform a Finalize method, which is only used in the processing of non-manageable resources. Since Finalizer needs to take a certain resource, it should only be implemented in the method that needs it needs to be executed. The Finalize method that directly calls an object is absolutely not allowed (unless the Finalize of the base class is called in the finalize of the subclass.), The debris collection program automatically calls Finalize. From the grammar, the Destructor in C # is very similar to C , but in fact they are completely different. The Destructor in C # just defines the shortcut to the Finalize method. Therefore, the following two codes are different: ~ myclass () {// Need to complete tasks} myclass.Finalize () {// Need to complete task base.Finalize ();}
Error 2: Who is Finalize and Dispose? From the above discussion we have clearly, call Finalizer, which is not allowed, it can only be called by the fragmented collection program. If you want to release some non-manageable resources (such as a file handle) as soon as possible, you should use the IDisposable interface, this interface has a Dispose method, which can help you complete this task. Dispose is a way to release non-manageable resources without waiting for Finalize being called. If the Dispose method has been used, it should block the fragment collection program to perform a Finalize method for the corresponding object. To this end, you need to call the static method gc.suppressFinalize, and pass the corresponding object's pointer to it as a parameter, the Finalize method can call the Dispose method. According to this, we can get the following code: public void dispose () {// complete cleaning operation // Notification GC Do not call finalize method gc.suppressFinalize (this);} public override void finalize () {Dispose (); base .Finalize ();} For some objects, it may be more appropriate (for example, for file object calls CLOSE is more appropriate than Dispose), you can create a private property of the Dispose method and the Close method of the public property, and let CLOSE calls Dispose to implement a Close method for some objects. Since it is not possible to determine, Dispose will be called, and the implementation of Finalizer is not determined (we can't control GC when running), C # provides a USING statement to ensure that the Dispose method will be called as long as possible. The general method is to define which object used, then use parentheses to specify a range of activities, when encountering the innermost parentheses, the Dispose method will be automatically called, and the object is processed. Using system.drawing; class tester {public static void main () {using (font thefont = new font) {// Using the Thefont Object} // The compiler will call Dispose to process thefont object font anotherfont = New font ("Courier", 12.0F); Using (anotherfont) {// Using anotherfont object} // The compiler will call the Dispose to process anotherfont object}}}
In the first part of this example, the Font object is created in the USING statement. When the USING statement ends, the system will call Dispose to process the Font object. In the second part of this example, the Font object is created outside the USING statement. When you decide to use it, put it in the USING statement, and when the USING statement ends, the system will call Dispose. The USING statement also prevents other unexpected occurrences, ensuring that the system will call Dispose. Error 3: Validity variables in C # and reference variables are different from C , and C # is also a strong type programming language. The data type in the C # is divided into two major categories: the C # language itself is inherent, the user-defined data type, which is similar to C . In addition, the C # language also divides variables into values and reference types. Unless it is included in a reference type, the value of the value type variable is retained in the stack, which is very similar to the variables in C . The reference type variable is also one of the stack. Its value is the address of the object in the heap, which is very similar to the pointer in C . The value of the value type variable is passed directly to the method, and the reference variable passes the index when transmitted to the method as a parameter. The class and interface can create a reference class variable, but it is to be pointed out that the structure data type is a built-in data type of C #, and is also a value type data type. Error 4: Note The Data Type Conversion Boxing and Unboxing are two processes that make the value data type used as the index type data type. Valid type variables can be packaged in an object and then unpacked the invalidation variable. The data types including all C # including built-in data types can be implicitly converted to an object. Packaging a value variable generates an instance of an object, then copy the variable to an instance. Boxing is implicit, and if the value of the value data type is used in a place where the index type data type is required, the value variable is implicitly converted to the variable of the indexed data type. Boxing will affect the performance of the code, so it should be avoided, especially when the amount of data is large. If you want to convert a packaged object back to the original value variable, it must be explicitly unpacking. Unpacking requires two steps: First check the object instance, make sure they are packaged by the value of the value of the value; second step copies the values in the instance into the value variable. In order to ensure the success of the unpack, the unbearable object must be an index of an object that generates a value of a value variable. Using system; public class unboxingtest {public static void main () {INT i = 123; // Package Object O = I; // Unpack (must be dominated) INT J = (int) O; console.writeline "J: {0}", J);}}
If the object being unbealed is invalid, or an index of a different data type object, an invalidcastexception is produced. Error 5: Structure and objects are different from C structures and classes, the only difference is that in the default, the access rights of the structure are public, and their inheritance is also public. Some C programmers use the structure as a data object, but this is just a convention and must not be like this. In C #, the structure is just a user-defined data type and cannot replace classes. Although structures also support attributes, methods, domains, and operators, but do not support inheritance and Destructor. More importantly, the class is an index type data type, and the structure is a value data type. Therefore, the structure is more useful in expressing objects that do not require indexing operations. The structure is more efficient in array operation, and the efficiency is less efficient in terms of the operation of the collection. The collection requires an index, the structure must be packaged to be used in the operation of the collection, and the efficiency in the larger scale operation is higher. Error 6: The virtual method must be explicitly covered in the C # language, and the programmer must explicitly use Override Gutthewword when overwriting an imaginary method. Suppose a Window class is written by Company A, the Listbox and Radiobutton classes are written on the basis of the WINDOW class written by B and programmers in the purchase of the WINDOW class, including the future change of the Window class. There is very little design in the situation. This will not have any questions before the new version of the Window class, a new version of the Window class, a new version of the Window class, which is new version of the Window class. If a company's programmer has also added a Sort method in the Window class. Public class window {// "public virtual void sort () {"}} In C , the Sort method in the Windows class will become a listbox class. In the basic method of the Sort method, when you want to call the Sort method in the Windows class, the Sort method in the ListBox class will be called. In C #, the virtual function is always considered to be the root of the virtual schedule. That is to say, once C # Discover a virtual method, no other virtual method in the virtual chain. If ListBox is compiled again, the compiler will generate a warning message: "/class1.cs (54, 24): Warning CS0114: ' Listbox.sort () 'HIDESINHERITED Member' Window.Sort () '. To cover the original method, you need to add Override care, or add New Getting. To eliminate warning information, programmers must figure out what he wants to do. New NEW can be added before the Sort method in the ListBox class, indicating that it should not overwrite the imaginary method in the Window: public class listbox: window {public new virtual void sort () {"} This will clear the warning message. If the programmer is indeed Want to override the method in Window, you must use Override Guanjian word to explicitly indicate its intent.
Error 7: Initialization in the initialization of class member variables is different from C . Suppose there is a Person class with a PRIVATE nature, Employee is generated by inheriting the Person class, which has a private nature SalaryLevel member variable. In C , we can initialize SalaryLevel in the initialization part of Employee constructor, as shown in the following code: Employee :: Employee (int theage, int theagelelevel): Person (theage) // Initialize the base class SALYLEVEL / THHESALYLEVEL / / Initialize the code of the member variable {// constructor} This method is illegal in C #. Although the basic class can still be initialized, it will cause compilation errors as the code above the code. In C #, we can initialize it while defining a member variable: Class Employee: Public Person {// member variable definition private salesLEVEL = 3; // Initialization} Note: Access to each variable must be explicitly defined Permission. Error 8: Booler variable and integer variable are two things IF (SomefuncWhichreturnsavalue ()) In C #, the Booler-type variable is different from the integer variable, so the following code is incorrect: if (SomefuncWhichreturnsavalue ()) IF SomeFuncWhichreturnsavalue returns zero to represent false, otherwise true's idea is not available. Such a benefit is that there is no more confused error that will assign a value and equivalent. So the following code: if (x = 5) is wrong when compiling, because x = 5 is just gives 5 to X instead of a Boolean value. Error 9: Some statements will be executed in the switch statement to do not in C #, if a Switch statement has executed some operations, the program may not be executed to the next statement. Therefore, although the following code is legal in C , it is not legal in C #: Switch (i) {case 4: CallFuncone (); case 5: // error, not executing Callsomefunc ();}