• Featured post

C# Task async programming (TAP) and parallel code

The core for asynchronous programming are the objects Task and Task<T>. Both of them are compatible with the keywords async and await.

First of all we need to identify if the code’s I/O-bound or CPU-bound.

  • the code’s limited for external operations and waits for something a lot of time. Examples of this are DDBB calls, or a server’s response. In this case we have to use async/await to free the thread while we wait
  • the code does a CPU-intensive operation. Then we move the work to another thread using Task.Run() so we don’t block the main thread.

async code vs parallel code

(!) Asynchronous code is not the same as parallel code (!)

  • In async code you are trying to make your threads do as little work as possible. This will keep your app responsibe, capable to serve many requests at once and scale well.
  • In parallel code you do the opposite. You use and keep a hold on a thread to do CPU-intensive calculations

async code

The importante of async programming is that you choose when to wait on a task. This way, you can start other tasks concurrently

In async code, one single thread can start the next task concurrently before the previous one completes.
(!) async code doesn’t cause additional threads to be created because an async method doesn’t run on its own thread. (!) It runs on the current synchronization context and uses time on the thread only when the method is active.

parallel code

For parallelism you need multiple threads where each thread executes a task, and all of those tasks are executed at the same time

Read More

C# Raw string literals

Before raw string literals

The main problems with long string literals were:

  • strings that include double quotes tend to be unreadable
  • identation looks messy in multiline strings

we have the following json we want to put into a string literal

{
	"number": 42,
	"text": "Hello, world",
	"nested": { "flag": true}
}

an ordinary quoted string literal looks like this:

string json = "{\r\n  \"number\": 42,\r\n  \"text\": \"Hello, world\",\r\n  \"nested\": { \"flag\": true }\r\n}"

verbatim string literals work slightly better here but will be missaligned when used over nested code. Also quotes look different as they still need to be scaped.

foreach(var item in list)
{
	if(Check(item))
	{
		string json = @"{
  ""number"": 42,
  ""text"": ""Hello, world"",
  ""nested"": { ""flag"": true }
}";
	}
}

Using raw string literals

Here’s how this example looks using raw literals.

foreach(var item in list)
{
	if(Check(item))
	{
		string json = """
		{
			"number": 42,
			"text": "Hello, world",
			"nested": { "flag": true }
		}
		""";
	}
}

Inside raw literals we don’t need to scape chars. Also we’re able to indent our code.

Read More

C# Anonymous methods and lambda expressions

Named method vs anonymous method

A named method is a method that can be called by its name:

// named method declaration
public string Join(string s1, string s2)
{
	return s1+s2;
}
// named method usage
var result = Join("this is ", "a joined string");

An anonymous method is a method that is passed as an argument to a function, without the need for its name. These methods can be constructed at runtime or be evaluated from a lambda expression.

// declaration
public void ProcessBook(Action<Book> process, List<Book> books)
{
	foreach (Book b in books)
	{
		process(b);
	}
}
// usage - print book titles
ProcessBook(bookList, book => Console.WriteLine(book.Title))

Here book => Console.WriteLine(book.Title) is the lambda expression and it’s result is an anonymous function that will be run by the method ProcessBook

Read More

C# Partial classes

A partial class in c# can be used to split functionality across multiple files, each with the same namespace and name.

A good use case for them is to use them as a stepping-stone in refactoring god-classes. If a class has multiple responsibilities (really large files), it may be a TEMPORAL way to refactor & split behaviours, before splitting them into different classes.

Usually, you can’t have 2 classes with the same name. This is unless you mark them as partial.

// this works fine, although it's not the best use case
public partial class MyClass
{
	public bool Ok { get; set; }
}

public partial class MyClass
{
	public bool IsOk()
	{
		return Ok;
	}
}

When you have multiple partial classes the compiler will merge them all into one single class.
Some rules:

C# Pattern matching

Overview of scenarios where you can use pattern matching. These techniques can improve the readability and correctness of your code.

Reduce nested if-else

I have a complex nested if-else statements scenario

// DON'T DO THIS
if (order.Status == "Pending")
{
	ProcessPendingOrder(order);
} else if (order.Status == "Completed")
{
	ProcessCompletedOrder(order);
} else if (order.Status == "Cancelled")
{
	ProcessCancelledOrder(order);
} else
{
	throw new InvalidOperationException("Unknown status");
}

instead do this

order.Status switch
{
	"Pending" => ProcessPendingOrder(order),
	"Completed" => ProcessCompletedOrder(order),
	"Cancelled" => ProcessCancelledOrder(order),
	_ => throw new InvalidOperationException("Unknown status")
};

Using it as a method

You can test a variables to find a match on specific values

public State PerformOperation(string command) =>
	command switch
	{
		"SystemTest" => RunDiagnostics(),
		"Start" => StartSystem(),
		"Stop" => StopSystem(),
		_ => throw new ArgumentException("Invalid string value", nameof(command)),
	};

_ is the discard pattern that matches all values. It handles any error conditions where the value doesn’t match one of the defined values.

Read More

C# Expression bodied members

Expression body definitions let you provide a member’s implementation in a concise, readable form.

Methods

Expression-bodied method consists of a single expression that returns:

  • a value whose type matches the return value
  • or performs an operation for void methods
public class Person(string firstName, string lastName)
{
	public override string ToString() => $"{firstName} {lastName}".Trim();
	public void DisplayName() => Console.WriteLine(ToString());
}

Read-only properties

You can use them to implement read-only property.

public class Location(string locationName)
{
	public string Name => locationName;
}

Reference(s)

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members

C# Collections' index and range operators

Index operator ^1

The index operator is used to reach the last positions of an array or list.

before

List<int> arr = [0, 1, 2, 3, 4, 5];
if(arr[arr.Count-1] == 5)
	Console.WriteLine("match!"); // prints

same but using index operator

List<int> arr = [0, 1, 2, 3, 4, 5];
if(arr[^1] == 5)
	Console.WriteLine("match!"); // prints

we can use it to reach any position starting from the back

List<int> arr = [0, 1, 2, 3, 4, 5];
if(arr[^2] == 4)
	Console.WriteLine("match!"); // prints

Read More

Deconstruction in ASP.NET Core

Desconstructors allows us to extract in a single expression, properties of an object or elements of a tuple, and assign them to distinct variables.

record and record struct automatically provide a Deconstruct method.

Classes

before deconstruction we had to manually extract each variable

var pat = new Person() { Name = "Patrick", BirdDate = new DateOnly(1999, 1, 18)};
var name = pat.Name;
var birthDate = pat.BirthDate;
Console.WriteLine($"Name: {name}, birthdate: {birthDate}");

class Person

public class Person
{
	public string Name { get; set; }
	public string Location { get; set; }
}

with deconstruction

var pat = new Person() { Name = "Patrick", BirdDate = new DateOnly(1999, 1, 18)};
var (name, birthDate) = pat;
Console.WriteLine($"Name: {name}, birthdate: {birthDate}");

class Person with Deconstructor

public class Person
{
	public string Name { get; set; }
	public string Location { get; set; }
	
	public void Deconstruct(out string name, out string location) 
	{
		name = Name;
		location = Location;
	}
}

if you don’t want all properties, just discard some using the discard character _

var pat = new Person() { Name = "Patrick", BirdDate = new DateOnly(1999, 1, 18)};
var (name, _) = pat;
Console.WriteLine($"Name: {name}");

Tuples

The same applies to tuples

// tuple creation
(string name, string location) person = ("mario", "spain");
// deconstructor
var (name, location) = person;

Reference(s)

https://blog.ndepend.com/deconstruction-in-c/

Cache in ASP.NET Core

ASP.NET Core offers several cache types. I’m going to explore here IMemoryCache which stores data in the memory of the web server. It’s simple but not suitable for distributed scenarios.

first of all we need to register the services

builder.Services.AddMemoryCache();

here’s how you can use it

public service(IMemoryCache cache, AppDbContext context)
{
	public Person GetPerson(string id)
	{
		if(!cache.TryGetValue(id, out Person person))
		{
			person = context.Persons.Find(id);

			var cacheEntryOptions = new MemoryCacheEntryOptions()
				.SetAbsoluteExpiration(TimeSpan.FromMinutes(10))
				.SetSlidingExpiration(TimeSpan.FromMinutes(2));

			cache.Set(id, person, cacheEntryOptions);
		}

		return person;
	}
}

Reference(s)

https://www.milanjovanovic.tech/blog/caching-in-aspnetcore-improving-application-performance

Dependency injection in .NET Core

Dependency injection is native-available in .NET Core

DI implementation

interface we want to inject

public interface IDateTime
{
	DateTime Now { get; }
}

interface’s implementation

public class SystemDateTime : IDateTime
{
	public DateTime Now
	{
		get { return DateTime.Now; }
	}
}

service we inject into

public class HomeController : Controller
{
	private readonly IDateTime _dateTime;

	public HomeController(IDateTime dateTime)
	{
		_dateTime = dateTime;
	}

	public IActionResult Index()
	{
		var serverTime = _dateTime.Now;
		return Ok(serverTime);
	}
}

Read More

C# Anonymous types objects

Anonymous types provide an easy way to encapsulate different properties in a single object. Unlike properties in a class, the properties of anonymous type objects are read-only.

Declare and use anon type objects

declaration

var loginCredentials = new { Username = "suresh", Password = "******" };
Console.WriteLine($"Username {loginCredentials.Username.ToString()}");
Console.WriteLine($"Password {loginCredentials.Password.ToString()}");

After assigning values to the Username and Password properties, they cannot be altered *(they’re readonly).

Anon objects in LINQ

Usually, anon data types are used in the select clause to return a specific subset of properties for each object in the collection.

we have the employee class

public class Employee
{
	public int ID { get; set; }
	public string Name { get; set; }
	public int Age { get; set; }
	public string Address { get; set; }
}
List<Employee> employees = // whatever ...
// we convert an Employee into an anon object type with a subset of properties
var employeeDetails = from emp in employees
	select new { Id = emp.ID, Name = emp.Name };

Reference(s)

https://www.syncfusion.com/blogs/post/understanding-csharp-anonymous-types