[FromE liangshi Yiyou Network] Although most of the errors discussed in this article are for C #, some errors are also related to other CLR-oriented languages or frameworks class library (FCL) languages. Five common errors described below:
Common error 1: Use a reference as a value or vice versa
Programmers in C ++ and many other languages are used to assigning values to variables either simple values or references to existing objects. However, in C #, whether it is a value or a reference is determined by the programmer who writes the object, rather than the programmer who instantiates the object and assigns a value. This will often lead to new C # programmers.
If you don't know whether the object you are using is a value type or a reference type, you may be pleasantly surprised. For example:
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2plfqfdt7gtnrxaaarnblxvw4936.png "Height =" 244 "width =" 480 "/>
As you can see, although the point and pen objects are created in the same way, the value of point1 remains unchanged when a new x coordinate value is assigned to point2. When a new color value is assigned to pen2, pen1 also changes. Therefore, we can infer that both point1 and point2 contain copies of their point objects, while pen1 and pen2 reference the same pen object. How can we know this principle without this test?
One way is to see how the object is defined (in Visual Studio, you can place the cursor on the object name and press the F12 key)
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2PlFQFdu-Spk6tAAALkK_Jv4g950.png "/>
As shown above, in C #, the struct keyword is used to define a value type, while the class keyword is used to define the reference type. For those who have a C ++ programming background, if they are confused by some similar keywords between C ++ and C #, they may be surprised by the above behavior.
If the behavior you want to depend on varies with the value type and reference type, for example, if you want to pass an object as a parameter to a method, modify the object status in this method. Make sure that you are processing the correct type object.
Common Error 2: misunderstanding the default value of uninitialized variables
In C #, the value type cannot be blank. According to the definition, the type value of the value or even the value type of the initialization variable must have a value. This is the default value of this type. This usually causes the following unexpected results to check whether a variable is not initialized:
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2plfqfdwlyfdynaaavz4tzvkg227.png "Height =" 119 "width =" 498 "/>
Why not [point 1] is null? The answer is that a point is a value type, which is the same as the default value (0, 0) and has no null value. Failed to realize this is a very simple and common error, in C #
Many (but not all) value types have an "isempty" attribute. You can see that it is equal to the default value:
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2plfqfdxkacs_saaage9d6s00008.png "/>
When you check whether a variable has been initialized, make sure that you know that the value is not initialized as the type of the variable. By default, the value is not null.
Common error 3: Use an inappropriate or unspecified method to compare strings
There are many methods in C # To compare strings.
Although many programmers use the = Operator to compare strings, this method is not recommended. The main reason is that this method does not specify the type used to compare strings in the code.
On the contrary, it is best to use the equals method to determine whether the string is equal in C:
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2plfqfdx6ikrx3aaalrvdnj2q156.png "/>
The first equals method (without the comparisontype parameter) returns the same result as the = Operator, but the advantage is that it explicitly specifies the comparison type. It compares strings by byte in sequence. In many cases, this is the expected comparison type, especially when comparing strings set through programming, such as file names, environment variables, and attributes. In these cases, only the byte-by-byte comparison can be performed. The only bad thing about comparing using the equals method without the comparisontype parameter is that those who read your program code may not know what the comparison type is.
Using the equals method with comparisontype to compare strings not only makes your code clearer, but also makes you think about which type to compare strings. This method is worth using, because although there are not many differences between the sequential comparison and the comparison by language region in English, however, some other languages may be quite different. If you ignore this possibility, you will undoubtedly dig a lot of traps for yourself in the future ". For example:
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2PlFQFdyvBCj9iAAA-uYWMGc0309.png "Height =" 234 "width =" 486 "/>
The safest practice is to always provide a comparisontype parameter for the equals method.
The following are some basic guiding principles:
When comparing user input strings or displaying string comparison results to users, use localized comparison (currentculture or currentcultureignorecase ).
When comparing strings for programming, use the original comparison (ordinal or ordinalignorecase)
Invariantculture and invariantcultureignorecase are generally not used unless in a restricted situation, because the original comparison is usually more efficient. If the comparison related to local culture is essential, it should be executed based on the comparison of the current culture or another special culture.
In addition, for the equals method, the string usually provides the compare method, which can provide the relative sequence information of the string rather than simply testing for equality. This method applies well to the <, <=,> and> = operators.
Common error 4: Use iterative statements instead of declarative statements to operate on the set
In C #3.0, the introduction of LINQ changes the previous query and modification operations on the set objects. From this point on, you should use LINQ to operate the set, rather than iteration.
Some C # programmers do not even know the existence of LINQ. Fortunately, the number of people who do not know is gradually decreasing. However, some people mistakenly think that LINQ is only used for database queries, because the keyword of LINQ and SQL statements are too similar.
Although the database query operation is a typical application of LINQ, it can also be applied to various enumerated set objects. (For example, any object that implements the ienumerable interface ). For example, if you have an array of the Account type, do not write it as follows:
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2PlFQFd0KzEPw-AAAMicDdUNQ028.png "Height =" 71 "width =" 500 "/>
You only need to write as follows:
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2plfqfd1mbfrnoaaanouke68e014.png "Height =" 63 "width =" 442 "/>
Although this is a simple example, in some cases, a single LINQ statement can easily replace dozens of statements in an iteration loop (or nested loop) in your code. Less Code usually means fewer bugs are introduced. However, remember, you may have to weigh the performance. In scenarios where performance is critical, especially when your iterative code can make assumptions about your set, you must compare the performance between the two methods.
Common error 5: underlying objects are not taken into account in the LINQ statement.
For processing abstract operations on a set of tasks, LINQ is undoubtedly large. Whether they are in-memory objects, database tables, or XML documents. In such a perfect world, you do not need to know the underlying objects. The mistake here is to assume that we live in a perfect world. In fact, the same LINQ statement can return different results. When executed on the exact same data, if the data happens to be in a different format.
For example, consider the following statement:
650) This. width = 650; "src =" http: // 183.61.143.148/group1/m00/01/F5/tz2plfqfd5xddqeyaaamnnqbw2m732.png "/>
Imagine what will happen to the account of one of the objects. The status is equal to "valid" (note the upper case of )?
Well, if myaccout is a dbset object. (Different case-sensitive configurations are set by default), The where expression will still match this element. However, if myaccout is in the memory array, it will not match and thus produce different overall results.
Wait a moment. In the string comparison we have discussed before, we can see that the = Operator plays a simple comparison. so why does = show another form under this condition?
The answer is: when the basic objects in the LINQ statement reference data in the SQL table (for example, in this example, if the object framework is a dbset object ), the statement is converted into a T-SQL statement. Then follow the T-SQL rules instead of the C # rules, so the end of the comparison above is case insensitive. In general, even if LINQ is a useful and consistent way to query a set of objects, in reality, you also need to know whether your statement will be translated into any engine or other expressions than C # To ensure that the behavior of your code will be as expected at runtime.
Want to learn moreProgramming Language tutorialLog onE liangshi Yiyou Network.
This article is from the blog, please be sure to keep this source http://yuguotianqing.blog.51cto.com/9292883/1548403
C # five common programming errors