DEV Community

Cover image for 7 Common MISTAKES made by C# developers (+ How to avoid them)
ByteHide
ByteHide

Posted on • Updated on • Originally published at bytehide.com

7 Common MISTAKES made by C# developers (+ How to avoid them)

Developers will always make mistakes; no one is impeccable. Many of them, particularly C# developers, learn and grow via trial and error. I prefer to refer to it as "transitioning" from junior to senior developer.

Although this "technique" of trial and error works, if a developer does not identify errors, they might cause several efficiency and quality issues in the developed application.

In this article, I've compiled a list of the most frequent and not-so-common mistakes made by C# developers.


1. Usage of String Concatenation

String Concatenation Functions are really simple to use.

When something is added to the string, a new address is immediately created in memory. The previous string is transferred to the new section, which now has a different location (this is not efficient at all).

Let's see an example:

List dotnetsaferTools = new List(){"Shield","Secrets","Linker"};
string tools = string.Empty;foreach (var tool in dotnetsaferTools)
{   
  tools += tool; // Creates a copy of the string in memory
}
Enter fullscreen mode Exit fullscreen mode

Solution

The way to solve this is simple, you have to use StringBuilder object instead of string aggregation which will keep the same position in memory without any copy task.

This simplifies and speeds up the string concatenation process, allowing us to smoothly add all of the actions we require.

This is how it would look like:

StringBuilder toolsBuilder = new StringBuilder();foreach (var tool in dotnetsaferTools)
{
  toolsBuilder.Append(tool);
}
Enter fullscreen mode Exit fullscreen mode

2. Iterating with Values instead of with LINQ

This problem happens when you attempt to iterate through a list of records using a loop, which is not optimum.

foreach (Customer customer in CustomerList) {
  if (customer.State == "ES") {
    tax += customer.Balance;
  }
}
Enter fullscreen mode Exit fullscreen mode

Solution

Instead of doing this, we should simply use LINQ which will allow us to query objects easily:

tax = CustomerList.Where(customer => customer.State.Equals("ES")).Sum(c=>c.Balance);
Enter fullscreen mode Exit fullscreen mode

📚Note: This is more efficient than a foreach loop.


3. Not using Yield Return

This is for when you need to create an object enumeration for some other caller. Using this function will greatly improve performance.

Solution

To prevent making this error, simply do not attempt to build a return collection. The main benefit of utilizing yield return is that the complete collection does not need to be held in memory.

This will allow you to have control after each iteration and you will only process the results that you need and that are necessary.


4. Deferred Execution in LINQ

The main one of LINQ is to facilitate querying data in case we use foreach loops (an example is nested if blocks). To get a list of clients, I recommend using LINQ-to-SQL.

public IEnumerable GetCustomer()
{
  using(var context = new DBContext())
  {
    return from c in context.Customer
      where c.Balance > 5000
      select c;
  }
}
Enter fullscreen mode Exit fullscreen mode

Everything appears to be in order, doesn't it? Only until we try to count the items in the collection (it will return an exception).

LINQ will not conduct any queries until we try to enumerate the results.

Solution

The solution is simple, just convert all LINQ queries to a ToArray(). By doing this, LINQ should evaluate the queries before anything else.


5. Accessing Virtual Members within a Constructor

Although this error is not one of the first, it is one of the most common, although it may not seem so.

When an overridden method is called directly from the constructor of a base class, this error will appear because it comes from executing code before its time.

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");
  }
}
Enter fullscreen mode Exit fullscreen mode

Solution

Although it may seem very complex, it is actually very easy. We simply have to mark that class as sealed.
By doing this, we make sure that when we call the virtual method, we will not receive any warning.


6. Not knowing the importance of USING for Object Disposal

As partech.nl says, many C# developers are +unfamiliar* with the concept that the using keyword is not only used as a directive for adding namespaces, but is also very beneficial for object removal.

Solution

If you are really sure that an object should be deleted when performing certain actions, simply use the using statement to make sure that the object has been deleted correctly.

Let's see an example:

using(DisposableClass DisposableObject = new DisposableClass())
{
  DisposableObject.DoTheJob();
}// Does the same as:DisposableClass DisposableObject = new DisposableClass();
try
{
  DisposableObject.DoTheJob();
}finally
{
  DisposableObject.Dispose();
}
Enter fullscreen mode Exit fullscreen mode

7. Using Weak Cryptographic Algorithms

Here we agree with Stackify, this error is simply based on the fact that many developers use obsolete or vulnerable encryption algorithms (which is very easy to avoid).

In this case we have for example SHA1 or RIPEMD160, which do not offer a current and very good level of security.

using System.Security.Cryptography;   
...   
var hashAlg = SHA1.Create();
Enter fullscreen mode Exit fullscreen mode

Solution

The solution to this is to** use stronger encryption algorithms**, for example:

SHA256 instead of SHA1
SHA512 instead of RIPEMD160
AES instead of TripleDES


Conclusion

Software development is the process of developing applications that can be shared with others. As software developers, we are responsible for creating the code that makes up the application, as well as designing and testing it. We are also responsible for updating or adding new features to an existing application when necessary.

The world of software development is changing: it's no longer just about coding, but also about solving problems, understanding user behavior and much more. That's why I hope you found this article useful!!

Top comments (1)

Collapse
 
damjand profile image
Damjan Dimitrov

For #1 we could use a simple one-liner:
string tools = String.Join(string.Empty, dotnetsaferTools)