5 C# Tips from a Senior Developer to Help You Program Better
Tags: csharp, dotnet, tutorial, productivity
Published: 2022-07-13 07:36:00


Senior developers tend to pick up many tricks and workarounds over the years, but most of them never make it into articles, blog posts or books. If you’re just starting out as a C# developer, or if you’re looking to **improve your skills**, here are some tips from some of a Senior Developer on how to program better using C#.

They will help you improve your coding abilities with this powerful language so, I hope you find these tips useful as you continue on your programming journey!

These guidelines are provided by [**Milan Jovanović**](https://www.linkedin.com/in/milan-jovanovic/), Senior Software Engineer at [HTEC Group](https://www.linkedin.com/company/htecgroup/), a huge technology company that has raised a whopping [**$140M** in its latest round of investment](https://htecgroup.com/insights/news/htec-group-announces-140m-investment-from-brighton-park-to-accelerate-global-expansion%e2%80%af/) alone!

I very recommend you to [follow him on Linkedin](https://www.linkedin.com/in/milan-jovanovic/) because he is always sharing valuable content about C#.

---

## Expression-Bodied Constructors

For this [first tip](https://www.linkedin.com/feed/update/urn:li:activity:6952198212967419905/), Milan reports that there is the possibility of **creating expression-bodied constructors** using the different characteristics introduced by the [tuples](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples):

> “You can create a tuple from the constructor arguments and then deconstruct that tuple into the respective properties.”

[Expression-bodied members](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members) have the ability to **easily provide the implementation of a member**. This is useful as long as the property or method consists of only a single expression.

Here Milan shows first the before:

```csharp
public class Person
{
    public string Name { get; }
    public int Age { get; }

    public Person (string name, int age)
    {
        Name = name;
        Age = age;
    }
}
```

Then, Milan shows the after of what it would look like:

```csharp
public class Person
{
    public string Name { get; }
    public int Age { get; }

    public Person(string name, int age) => (Name, Age) = (name, age);
}
```

Some people may think at first glance that this affects performance, but [Milan disproves this](https://www.linkedin.com/feed/update/urn:li:activity:6952198212967419905/):

> “It won’t affect performance! The compiler is smart enough to optimize the expression-bodied assignment into single statements.”

This tip seems to me a very good practice especially to avoid many lines of code and keep it clean and readable.

---

## DateOnly and TimeOnly Types

Milan begins by introducing this tip with a question that I’m sure more than one of you have asked yourself:

> “How many times did you only need to know about the Date component of a DateTime object?”

Previously this was not possible, but with the arrival of .NET 6, the Types [DateOnly](https://docs.microsoft.com/en-us/dotnet/api/system.dateonly?view=net-6.0) and [TimeOnly](https://docs.microsoft.com/en-us/dotnet/api/system.timeonly?view=net-6.0) were added.

And so Milan teaches us [how to put them into practice](https://www.linkedin.com/posts/milan-jovanovic_softwareengineering-csharp-csharptips-activity-6950720370060537856-UxQ_/?utm_source=linkedin_share&utm_medium=member_desktop_web):

```csharp
DateOnly todaysDate = new DateOnly(22, 1, 20);

DateOnly currentUtcDate = DateOnly.FromDateTime(DateTime.UtcNow);
```

```csharp
// A couple constructors to choose from.
public TimeOnly(int hour, int minute)
public TimeOnly(int hour, int minute, int second)
public TimeOnly(int hour, int minute, int second, int millisecond)

TimeOnly nineInTheMorning = new TimeOnly(9, 0);

TimeOnly currentUtcTime = TimeOnly.FromDateTime(DateTime.UtcNow);
```

However, Milan warns us that, for example **PostgreSQL EF Core**, already handles these new types without any problem. On the other hand, SQL Server does not at the moment:

> “Unfortunately, it seems some EF Core providers — looking at you, SQL Server — still aren’t up to speed with the new types.”

---

## Lazy Exception Caching

For this [third tip](https://www.linkedin.com/posts/milan-jovanovic_softwareengineering-dotnet-csharp-activity-6948580800103677952-wSCA), Milan tells us a bit about the .NET Lazy class. He wanted to focus on the **exception caching behavior**:

> “If your initialization logic throws an exception, the **Lazy** instance will cache that exception. Subsequent access to the [**Lazy.Value**](https://docs.microsoft.com/en-us/dotnet/api/system.lazy-1.value?view=net-6.0) property will throw that exception again.”

In addition, he warns that if we don’t really understand what is going on in that part of the code, we may have **different kinds of problems in the future**.

```csharp
var exceptionTrappingLazy = new Lazy(() => CallExternalService());

try{
    // Accessing the Value property will execute CallExternalSe4rvice()
    // Now, imagine that the external service is down
    // The call to CallExternalService() throws an exception
    var lazyValue = exceptionTrappingLazy.Value;
}
catch {...}

try
{
    //Accesing the Value property again won't call CallExternalService()
    //It will throw the trapped exception again!
    var lazyValueAgain = exceptionTrappingLazy.Value;
}
catch{...}
```

Finally, Milan reminds us that:

> “The lazy instance can and will cache exceptions, and keep throwing them during its lifetime.”

After these 3 tips, let’s look at a [series of tips also provided by Milan Jovanović](https://www.linkedin.com/posts/milan-jovanovic_how-to-use-minby-and-maxby-linq-methods-activity-6947492759008161792-r4oI?utm_source=linkedin_share&utm_medium=member_desktop_web). In these next tips Milan explains how to get the most out of the [MinBy](https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.minby?view=net-6.0) and [MaxBy](https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.maxby?view=net-6.0) methods, which were introduced in .NET 6.

Let’s take a look at them!

---

## How To Use MinBy and MaxBy LinQ Methods

In these examples Milan uses a couple of fruits and vegetables for a clear explanation. First, understand how `MinBy` and `MaxBy` work. For this we are going to use `MinBy` to find the **smallest value** and `MaxBy` to find the **highest value**. Let’s look at [Milan’s first example](https://www.linkedin.com/posts/milan-jovanovic_how-to-use-minby-and-maxby-linq-methods-activity-6947492759008161792-r4oI?utm_source=linkedin_share&utm_medium=member_desktop_web):

```csharp
public record Food (string Name, double Price);

var foodList = new List<Food>
{
    new("🍎", 1.15),
    new("🍌", 1.51),
    new("🥥", 2.99),
    new("🍋", 0.70),
    new("🥑", 9.13),
    new("🍄", 0.05),
};

//How do me find the cheapest food?

// How do we find the most expensive food?
```

### Find the smallest Value Object using MinBy

First it shows how it would look like in **.NET 5** (without `MinBy`):

```csharp
var cheapest = foodList.OrderBy(f => f.Price).List();
```

Then, Milan shows how it would look like in **.NET 6** (with `MinBy`):

```csharp
var cheapest = foodList.MinBy(f => f.Price);
```

In this case the result would be the **mushroom** “🍄” with `0.05` value (_which apparently is not being affected by inflation in this example_).

Sorry, let’s continue with the Milan examples:

### Find the highest Value Object using MaxBy

First it shows how it would look like in **.NET 5** (without `MaxBy`):

```csharp
var mostExpensive = foodList
    .OrderByDescending(f => f.Price)
    .First();
```

Then, Milan shows how it would look like in **.NET 6** (with `MaxBy`):

```csharp
var mostExpensive = foodList.MaxBy(f => f.Price);
```

In this case the result would be the **avocado** “🥑” with `9.13` value (_this one has been affected by inflation…_).

With these best practices we can maintain a cleaner code even though [Milan warns](https://www.linkedin.com/posts/milan-jovanovic_how-to-use-minby-and-maxby-linq-methods-activity-6947492759008161792-r4oI?utm_source=linkedin_share&utm_medium=member_desktop_web):

> “Also, don’t try using them inside an EF Core query!  
> At the moment, they are not present in the EF provider.”

Keep it in mind developers!

---

Thanks again to **Milan Jovanović** for sharing these guidelines and bringing value to the great and wonderful community of C# developers. If you liked them I would recommend you to [follow him on Linkedin](https://www.linkedin.com/in/milan-jovanovic/) because he is always active and uploads a lot of valuable C# content!