7 Common MISTAKES made by C# developers (+ How to avoid them)
Tags: csharp, dotnet, programming, netcore
Published: 2021-10-28 14:33:00

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:

```csharp
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
}
```

### 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:

```csharp
StringBuilder toolsBuilder = new StringBuilder();foreach (var tool in dotnetsaferTools)
{
  toolsBuilder.Append(tool);
}
```

---

## 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.**

```csharp
foreach (Customer customer in CustomerList) {
  if (customer.State == "ES") {
    tax += customer.Balance;
  }
}
```

### Solution

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

```csharp
tax = CustomerList.Where(customer => customer.State.Equals("ES")).Sum(c=>c.Balance);
```

> **📚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.**

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

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.

```csharp
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");
  }
}
```

### 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:

```csharp
using(DisposableClass DisposableObject = new DisposableClass())
{
  DisposableObject.DoTheJob();
}// Does the same as:DisposableClass DisposableObject = new DisposableClass();
try
{
  DisposableObject.DoTheJob();
}finally
{
  DisposableObject.Dispose();
}
```

---

## 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.

```csharp
using System.Security.Cryptography;   
...   
var hashAlg = SHA1.Create();
```

### 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!!