c++| programming
10 C # errors easily made by C + + programmers
We know that C # 's syntax is very similar to C + +, and the transition from C + + to C # is not the language itself, but the familiarity. NET's manageable environment and understanding of the. NET Framework.
Although C # and C + + in the grammatical changes are very small, almost no impact on us, but some changes are enough to make some of the careless C + + programmers always remember. In this article, we'll discuss 10 of the easiest mistakes that C + + programmers can make.
Trap 1: No definitive End method
It is almost entirely certain that, for most C + + programmers, C # is the biggest difference from C + + is in the collection of fragments. This also means that programmers no longer have to worry about memory leaks and ensure that all the useless pointers are removed. But we can no longer control precisely the process of killing unwanted objects. In fact, there is no clear destructor in C #.
If you use unmanaged resources, you must explicitly release the resources after you do not use them. Implicit control over resources is provided by the Finalize method (also known as finalizer), and when the object is destroyed, it is invoked by the fragment collector to reclaim the resource occupied by the object.
Instead of involving other objects, finalizer should release only the unmanaged resources occupied by the objects being destroyed. If you use only manageable resources in your program, you do not have to or should not execute a Finalize method, which is only used in the handling of unmanaged resources. Because finalizer requires a certain amount of resources, you should only perform finalizer in the method that requires it.
The Finalize method that calls an object directly is absolutely not allowed (unless you call finalize of the underlying class in finalize of the subclass). ), the defragmenter automatically invokes finalize.
Syntactically, destructor in C # is very similar to C + +, but in fact they are completely different. destructor in C # is just a shortcut to defining a Finalize method. Therefore, the following two snippets of code are different:
~myclass ()
{
Tasks that need to be completed
}
Myclass.finalize ()
{
Tasks that need to be completed
Base. Finalize ();
}
Who is wrong 2:finalize and dispose to use?
It is clear from the above discussion that the explicit invocation of finalizer is not allowed and can only be invoked by the fragment collector. If you want to free up a limited number of unmanaged resources (such as file handles) that you no longer use, you should use the IDisposable interface, which has a Dispose method that can help you accomplish this task. Dispose is a method that frees unmanaged resources without waiting for finalize to be invoked.
If you have already used the Dispose method, you should prevent the defragmenter from executing the Finalize method on the corresponding object. To do this, you call the static method GC. SuppressFinalize and passes the pointer of the corresponding object to it as an argument, the Finalize method can call the Dispose method. Accordingly, we can get the following code:
public void Dispose ()
{
Complete cleanup operation
Notifies the GC not to call the Finalize method again
Gc. SuppressFinalize (this);
}
public override void Finalize ()
{
Dispose ();
Base. Finalize ();
}
For some objects, it might be more appropriate to call the Close method (for example, a file object call Close is more appropriate than dispose) by creating a Dispose method of a private property and a close method of the public property. And let close call Dispose to implement the Close method call to some objects.
Because it is not certain that dispose will be invoked and finalizer execution is uncertain (we cannot control when the GC will run), C # provides a using statement to ensure that the Dispose method is invoked as early as possible. The general approach is to define which object to use, then specify an active range for those objects with parentheses, and when the most inner bracket is encountered, the Dispose method is automatically invoked to process the object.
Using System.Drawing;
Class Tester
{
public static void Main ()
{
using (Font Thefont = new Font ("Arial", 10.0f)
{
Using the Thefont object
The//compiler will call Dispose processing Thefont object
Font anotherfont = new Font ("Courier", 12.0f);
using (Anotherfont)
{
Using the Anotherfont object
The//compiler will call Dispose processing Anotherfont object
}
}
In the first part of this example, the Font object is created in the using statement. When the using statement finishes, the system calls Dispose and handles the font object. In the second part of this example, the Font object is created outside the using statement, and when you decide to use it, it is placed inside the using statement, and the system calls Dispose when the using statement ends.
The using statement also prevents other surprises from occurring, and guarantees that the system will call Dispose.
There is a difference between a value-type variable and a reference variable in the error 3:c#
Like C + +, C # is also a strongly typed programming language. The data types in C # are divided into two categories: The C # language itself is inherently a data type and a user-defined data type, which is similar to C + +.
In addition, the C # language divides variables into value types and reference types. Unless you are included in a reference type, the value of the value type variable remains on the stack, much like the variables in C + +. A variable of a reference type is also a stack, whose value is the address of the object in the heap, very similar to a pointer in C + +. The value of a value type variable is passed directly to the method, and the reference variable is passed as an index when it is passed as a parameter to the method.
Classes and interfaces can create reference class variables, but it should be noted that the struct data type is a built-in data type for C # and is also a value-type data type.
Error 4: Note the implicit data type conversion
Boxing and unboxing are two procedures that make a value type data type used as an indexed data type. A value variable can be wrapped into an object and then wrapped back into a value-type variable. All data types in C #, including built-in data types, can be implicitly converted to an object. Wrapping a value variable generates an instance of an object and then copies the variable into the instance.
Boxing is recessive, and if a value-type variable is used where the indexed data type is needed, the value-type variable is implicitly converted to the variable of the indexed data type. Boxing can affect the performance of code execution and should therefore be avoided, especially when the data volume is large.
If you want to convert a packaged object back to its original value variant, you must unpack it explicitly. The solution takes two steps: First, the object instance is checked to make sure that they are wrapped by a value-type variable, and the second step copies the value from the instance to the value type variable. To ensure that the package is successful, the unpacked object must be the index of the object that is generated by packing the value of a value variable.
Using System;
public class Unboxingtest
{
public static void Main ()
{
int i = 123;
Packaged
Object o = i;
Che Bao (must be dominant)
int j = (int) o;
Console.WriteLine ("J: {0}", j);
}
}
If the object being extracted is invalid, or an index of a different data type object, a InvalidCastException is generated.
Error 5: Structure differs from Object
The structure in C + + is similar to a class, except that, by default, the structure's access is public and its inherited permissions are public. Some C + + programmers use structs as data objects, but this is a convention rather than a necessity.
In C #, structs are just a user-defined data type and cannot be substituted for classes. Although structs also support properties, methods, fields, and operators, inheritance and destructor are not supported.
More importantly, the class is an indexed data type, and the structure is a value-type data type. Therefore, structs are more useful in expressing objects that do not require an index operation. Structs are more efficient in array operations and less efficient in the operation of collections. The collection requires an index, the structure must be packaged to be used in the operation of the collection, and the class is more efficient in a larger set operation.
Error 6: The virtual method must be explicitly overwritten
In the C # language, programmers must explicitly use the Override keyword when overwriting a virtual method. Suppose a window class is written by company A, the ListBox and RadioButton classes are written on the basis of the Windows class written by Company B and programmers in the purchase of company A, and B company programmers know little about the design of future changes including window classes.
If a programmer at Company B is going to add a sort method to the listbox:
public class Listbox:window
{
public virtual void Sort () {}
}
This will not be a problem until company a releases the new window class. If a company's programmers also add a sort method to the window class.
public class Window
{
// "
public virtual void Sort () {}
}
In C + +, the Sort method in the Windows class becomes the underlying method of the sort method in the ListBox class, and the sort method in the ListBox class is invoked when you want to call the sort method in the Windows class. In C #, virtual functions are always considered to be the root of a virtual schedule. That is, once C # discovers a virtual method, it no longer looks for other virtual methods in the virtual chain. If the listbox is compiled again, the compiler generates a warning message:
"\class1.cs (54,24): Warning CS0114: ' Listbox.sort () ' Hides
Inherited member ' Window.sort () '.
To get the current member to overwrite the original method, you need to add the override keyword, or add the new keyword.
To eliminate the warning message, the programmer has to figure out what he wants to do. You can add new before the Sort method in the ListBox class to show that it should not overwrite virtual methods in Windows:
public class Listbox:window
{
Public new virtual void Sort () {}
This allows you to clear the warning message. If programmers do want to overwrite the methods in window, they must use the Override keyword to explicitly indicate their intent.
ERROR 7: Initialization of class member variables
Initialization in C # differs from C + +. Suppose there is a person class with the private member variable age, which is generated by inheriting the person class and has a SALARYLEVEL member variable of private nature. In C + +, we can initialize SalaryLevel in the initialization section of the employee's constructor, as shown in the following code:
Employee::employee (int theage, int thesalarylevel):
Person (theage)//Initialize base class
SalaryLevel (thesalarylevel)//Initialize member variable
{
The code for the constructor
}
This method is illegal in C #. Although you can still initialize the underlying class, initializing a member variable like the code above causes a compilation error. In C #, we can initialize a member variable while it is defined:
Class employee:public Person
{
Definition of member variables
Private SalaryLevel = 3; Class
}
Note: You must explicitly define the access rights for each variable.
Error 8: Boolean variable and integer variable are two different things
if (Somefuncwhichreturnsavalue ())
In C #, a Boolean variable is not the same as an integer variable, so the following code is incorrect:
if (Somefuncwhichreturnsavalue ())
If Somefuncwhichreturnsavalue returns zero to false, otherwise the idea of true is no longer feasible. The advantage is that the original error of confusing assignment with equality is not repeated. So the following code:
if (x = 5)
An error occurs at compile time, because x=5 only assigns 5 to X, not a Boolean value.
Some statements in the error 9:switch statement do not execute
In C #, if a switch statement performs some action, the program may not be able to execute 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 executed here
Callsomefunc ();
}
To achieve the purpose of the above code, you need to use a goto statement:
Switch (i)
{
Case 4:
Callfuncone ();
Goto Case 5;
Case 5:
Callsomefunc ();
}
If the case statement does not execute any code, all statements will be executed. As in the following code:
Switch (i)
{
Case 4://able to execute to
Case 5://able to execute to
Case 6:
Callsomefunc ();
}
The variable in error 10:c# requires an explicitly assigned value
In C #, all variables must be assigned before they are used. Therefore, you can define a variable without initializing it, and you must be assigned a value before passing it to a method.
This can be problematic if you simply pass a variable by index to the method, and the variable is the output variable of the method. For example, suppose you have a method that returns the hour, minute, and second of the current time, if you write code as follows:
int thehour;
int Theminute;
int thesecond;
Timeobject.gettime (ref thehour, ref theminute, ref Thesecond)
If these three variables are not initialized before using Thehour, Theminute, and Thesecond, a compilation error is generated:
Use the unassigned local variable ' thehour '
Use the unassigned local variable ' theminute '
Use the unassigned local variable ' thesecond '
We can solve this small problem with the compiler by initializing these variables to 0 or other values that have no effect on the return value of the method:
int thehour = 0;
int theminute = 0;
int thesecond = 0;
Timeobject.gettime (ref thehour, ref theminute, ref Thesecond)
This is a bit too much trouble, these variables are passed to the GetTime method and then changed. To address this problem, C # provides an out parameter modifier specifically for this situation, which allows a parameter to be referenced without initialization. For example, the parameters in GetTime do not have a point in themselves, they are just to express the output of the method. Before returning in a method, a value must be specified in the out parameter. Here is the modified gettime method:
public void GetTime (out int h, out int m, out int s)
{
h = Hour;
m = Minute;
s = Second;
}
The following is the calling method for the new gettime method:
Timeobject.gettime (out of Thehour, out of Theminute, out Thesecond);