📜 ⬆️ ⬇️

C #: 10 common pitfalls and bugs

I bring to your attention the translation of the article about the "traps" in C #. This article will be useful for novice programmers who are not yet familiar with the subtleties of the language.

Enjoy reading.



“It's all the little things, little things. But nothing is more important than little things. ”

1. Using the wrong collection type


.Net has many collection classes, and they all specialize in specific tasks. The choice of class must be done carefully. Making a mistake in your choice, you will get an inefficient code, unexpected values, and also make the meaning of the code incomprehensible.
')
Read more here

2. Failure to yield return


When enumerating objects for a call, you should use the yield return operator, and not create a returning collection ( comment of the translator : depends on the situation). The advantages of this template:


3. Analysis of ambiguous dates


Be sure to specify the format, if we are talking about the analysis of ambiguous dates. For example, in the line “03/04/05” it is not clear what is the day, what is the month, and what is the year, and this can lead to serious errors for the user.

Here, use DateTime.ParseExact / DateTimeOffset.ParseExact to provide a format specifier:

var date = DateTime.ParseExact("01/12/2000", "MM/dd/yyyy", null) 

4. Reprocessing an exception with its instance


If you want to catch and re-process an exception, be sure to use a simple throw. If you suddenly use throw ex, it will not save the exception call stack.

Use:

 catch(SomeException ex) { logger.log(ex); throw; } 

And do not use:

 catch(SomeException ex) { logger.log(ex); throw ex; } 

5. Accessing virtual components in the constructor


A virtual descriptor allows class members to be redefined in a derived class. Constructors are executed along the path from the base class to the derived ones. That is, if you call an overridden method from the constructor of the base class, code that is not ready for execution may be called (this may depend on completion of initialization in its own constructor).

For example:

 public class Parent { public Parent() { Console.WriteLine("Parent Ctor"); Method(); } public virtual void Method() { Console.WriteLine("Parent method"); } } public class Child : Parent { public Child() { Console.WriteLine("Child Ctor"); } public override void Method() { Console.WriteLine("Child method"); } } 

Initialization of the child class will look like this:

  1. Parent designer
  2. Child method
  3. Child constructor

Those. The child method is called before the child constructor.

6. Exceptions in the static constructor


If a class throws an exception in the static constructor, it makes the class useless. Even non-static construction will be impossible. The class will generate a System.TypeInitializationException whenever it is referenced (statically or not).

7. Optional parameters in the external assembly


Optional parameters may not work as expected if they are referenced from an external assembly. Let's say you have some functionality packaged in a DLL. And, say, you want to make minor changes to the code (change the optional parameter to another value).

The consumer DLL will need to recompile in order for your changes to take effect.

Read more here

8. Universal methods with non-universal overload


Let's say you have a generic method that accepts a type parameter T and another method with the same name, but a receive parameter of a particular type. The compiler will choose a more suitable method for each type of parameter, and a clearly defined type is more correct than a universal one.

For example, there is the following class:

 class GenericTest { public void Test<T>(T parameter) { Console.WriteLine("Generic method!"); } public void Test(string parameter) { Console.WriteLine("Non-generic method!"); } } 

And the following code ...

 var instance = new GenericTest(); instance.Test(7); instance.Test("foo"); 

Will give you the result:

 Generic method! Non-generic method! 

Those. the compiler chooses a more specific string method on the second call.

9. Changing the hash code after adding an object to the dictionary


Dictionaries depend on the key values ​​returned by the Object.GetHashCode () method. This means that the hash code of the key cannot be changed after being added to the dictionary.

10. ValueType.Equals will slow down if the structure contains a reference component


Make sure that your structure does not contain a component reference if you want to use ValueType.Equals to compare two instances. Slow work is related to the fact that ValueType. Equals will use reflection to determine the reference component, and this may be a little slower than expected.

Original author: Robert Bengtsson

Source: https://habr.com/ru/post/322394/


All Articles