{"id":58644,"date":"2021-07-12T08:00:21","date_gmt":"2021-07-12T06:00:21","guid":{"rendered":"https:\/\/code-maze.com\/?p=58644"},"modified":"2024-03-22T12:21:48","modified_gmt":"2024-03-22T11:21:48","slug":"csharp-tips-improve-quality-performance","status":"publish","type":"post","link":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/","title":{"rendered":"Top 11 C# Tips to Improve Code Quality and Performance"},"content":{"rendered":"<p>In this article, we are going to learn some useful C# tips on how to improve our code quality and performance.\u00a0<\/p>\n<p>Let\u2019s get started!<\/p>\n<h2 id=\"why-we-chose-these-tips\">Why These C# Tips?<\/h2>\n<p>Before we begin, let us briefly discuss why we chose these specific C# tips over many others that certainly exist. With these tips, we can achieve a good balance of code quality and performance improvements. Note that some of these are only available with newer versions of C#, and we will state explicitly when that is the case.<\/p>\n<p>Also, these C# tips are relatively easy to integrate into an existing codebase. You will be able to apply these tips and reap the benefits, as soon as you are done reading this article.<\/p>\n<p>Whenever we write code, we are very likely to encounter:<\/p>\n<ul>\n<li>Guarding against null values<\/li>\n<li>If-else statements<\/li>\n<li>Exception handling<\/li>\n<li>Data Transfer Objects<\/li>\n<li>Collections<\/li>\n<\/ul>\n<p>So let us see how we can improve all of these in our code!<\/p>\n<h2 id=\"the-proper-way-to-do-a-null-check\">The Proper Way to Do a Null Checks<\/h2>\n<p>We perform null-checks quite often in our code, to guard against the dreaded <code>NullReferenceException<\/code>. The most common way we do this is:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var product = GetProduct();\r\n\r\nif (product == null)\r\n{\r\n    \/\/ Do something if the object is null.\r\n}<\/pre>\n<p>Do you know what the problem is with this approach? The <code>==<\/code> operator can be overridden and there is no strict guarantee that comparing an object with <code>null<\/code> will produce the result that we expect. Luckily, there is a new operator that is introduced in C# version 7, the <code>is<\/code> operator.<\/p>\n<p>Here is how we can perform a null-check with the new <code>is<\/code> operator:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var product = GetProduct();\r\n\r\nif (product is null)\r\n{\r\n    \/\/ Do something if the object is null.\r\n}<\/pre>\n<p>The <code>is<\/code> operator will always evaluate to <code>true<\/code> if the specified object instance is <code>null<\/code>. It is also a cleaner way of writing null-checks because it reads like a sentence.<\/p>\n<p>Beginning with C# 9, you can use a negation pattern to do a null-check:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var product = GetProduct();\r\n\r\nif (product is not null)\r\n{\r\n    \/\/ Do something if the object is not null.\r\n}<\/pre>\n<p>The same applies to this type of check, it will only evaluate to <code>true<\/code> if the specified object is not <code>null<\/code>. It can not be overridden.<\/p>\n<h2 id=\"how-to-reduce-nesting-in-your-code\">C# Tips to Reduce Nesting in Your Code<\/h2>\n<p>Nesting is when we have code between two curly braces. One simple example of nesting is the body of a method. We see that this is a natural occurrence in the language. However, we can face some problems when we have multiple levels of nesting.<\/p>\n<p>Why is code nesting a problem? Usually, one or two levels of nesting are not problematic. But, the more levels of nesting we have, the harder it becomes to read the code, and bugs will become harder to catch.<\/p>\n<p>Luckily, we can fix this easily. We are going to give you a few C# tips for reducing nesting in our code.<\/p>\n<p>Let us look at an example where we have an if-else statement. Inside the if-statement we are returning some value:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">Product PurchaseProduct(int id)\r\n{\r\n    var product = GetProduct(id);\r\n\r\n    if (product.Quantity &gt; 0)\r\n    {\r\n        product.Quantity--;\r\n\r\n        return product;\r\n    }\r\n    else\r\n    {\r\n        SendOutOfStockNotification(product);\r\n\r\n        return null;\r\n    }\r\n}<\/pre>\n<p>In cases like these, the entire else statement can be removed, and we are effectively reducing the nesting level for that part of the code:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">Product PurchaseProduct(int id)\r\n{\r\n    var product = GetProduct(id);\r\n\r\n    if (product.Quantity &gt; 0)\r\n    {\r\n        product.Quantity--;\r\n\r\n        return product;\r\n    }\r\n\r\n    SendOutOfStockNotification(product);\r\n\r\n    return null;\r\n}<\/pre>\n<p>Sometimes, we need to make sure that a couple of conditions are met before we perform some operation. This usually results in multiple levels of nesting and code that is harder to read:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">bool IsProductInStock(int id)\r\n{\r\n    var product = GetProduct(id);\r\n\r\n    if (product is not null)\r\n    {\r\n        if (product.Quantity &gt; 0)\r\n        {\r\n            return true;\r\n        }\r\n    }\r\n\r\n    return false;\r\n}<\/pre>\n<p>We can fix this by applying the \u201cearly return\u201d principle:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">bool IsProductInStock(int id)\r\n{\r\n    var product = GetProduct(id);\r\n\r\n    if (product is null)\r\n    {\r\n        return false;\r\n    }\r\n\r\n    if (product.Quantity &lt;= 0)\r\n    {\r\n        return false;\r\n    }\r\n\r\n    return true;\r\n}<\/pre>\n<p>The early return principle states that we should return from a method as soon as possible. In our case, we first check if the product is <code>null<\/code>, and return <code>false<\/code> if it is. Then we check if the quantity is less than or equal to zero, and return <code>false<\/code> if it is. Otherwise, the product is not <code>null<\/code> and the quantity is greater than zero, so we return\u00a0<code>true<\/code>.<\/p>\n<p>We can optimize this further by joining the two if-statements into a single one:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">bool IsProductInStock(int id)\r\n{\r\n    var product = GetProduct(id);\r\n\r\n    if (product is null || product.Quantity &lt;= 0)\r\n    {\r\n        return false;\r\n    }\r\n\r\n    return true;\r\n}<\/pre>\n<h3>Introducing Using Declarations<\/h3>\n<p>Using statements in the past always assumed an additional level of nesting in our code that was not necessary:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">using (var streamReader = new StreamReader(\"...\"))\r\n{\r\n    string content = streamReader.ReadToEnd();\r\n}\r\n<\/pre>\n<p>Starting with C# 8, we can remove the curly braces from the <code>using<\/code> statements in our code:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">using var streamReader = new StreamReader(\"...\");\r\n\r\nstring content = streamReader.ReadToEnd();\r\n<\/pre>\n<p>It is important to note that when using this feature, the <code>using<\/code> statement has block-level scope.<\/p>\n<h2 id=\"improve-logical-expression-readability\">Improve Logical Expression Readability<\/h2>\n<p>C# 9 introduced a set of new logical patterns that we can use to improve the readability of our logical expressions. Let us see how we can use them in our code!<\/p>\n<p>We are going to write a function to check if a specified character is a letter:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">bool IsLetter(char ch) =&gt; (ch &gt;= 'a' &amp;&amp; ch &lt;= 'z') || (ch &gt;= 'A' &amp;&amp; ch &lt;= 'Z');\r\n<\/pre>\n<p>This is the typical approach we would take, although it is a little cumbersome to write because we have to repeat the character parameter for every check.<\/p>\n<p>With the new <code>and<\/code> and <code>or<\/code> logical pattern combinators, we can rewrite the previous function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">bool IsLetter(char ch) =&gt; ch is (&gt;= 'a' and &lt;= 'z') or (&gt;= 'A' and &lt;= 'Z');\r\n<\/pre>\n<p>This new version is much more readable because it almost reads like a sentence. We also do not need to specify the character parameter more than once.<\/p>\n<h2 id=\"remove-if-else-statements-for-setting-boolean-values\">Remove If-Else Statements for Setting Boolean Values<\/h2>\n<p>We often encounter a situation in our code where we need to return a <code>bool<\/code> value from a function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">bool IsInStock(Product product)\r\n{\r\n    if (product.Quantity &gt; 0)\r\n    {\r\n        return true;\r\n    }\r\n    else\r\n    {\r\n        return false;\r\n    }\r\n}<\/pre>\n<p>Although this approach is mostly fine, we have to ask ourselves if we even need an if-statement in the first place. Since we already have a logical expression inside the if-statement, we can simplify the method by simply returning the value of that logical expression:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">bool IsInStock(Product product)\r\n{\r\n    return product.Quantity &gt; 0;\r\n}<\/pre>\n<p>We have to write far less code to achieve the same result, which is always desirable.<\/p>\n<p>We can further simplify the previous method by using an expression body:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">bool IsInStock(Product product) =&gt; product.Quantity &gt; 0;\r\n<\/pre>\n<p>If we notice that the boolean expression is becoming complex, we can split it into a couple of meaningfully named local variables.<\/p>\n<h2 id=\"how-to-simplify-switch-statements\">How to Simplify Switch Statements<\/h2>\n<p>Switch statements can be very useful when we want to evaluate some object, and based on the set of possible values return a different result.<\/p>\n<p>Let\u2019s write a switch statement to check if the current day is a weekend day or not:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">switch (DateTime.Now.DayOfWeek)\r\n{\r\n    case DayOfWeek.Monday:\r\n        return \"Not Weekend\";\r\n    case DayOfWeek.Tuesday:\r\n        return \"Not Weekend\";\r\n    case DayOfWeek.Wednesday:\r\n        return \"Not Weekend\";\r\n    case DayOfWeek.Thursday:\r\n        return \"Not Weekend\";\r\n    case DayOfWeek.Friday:\r\n        return \"Not Weekend\";\r\n    case DayOfWeek.Saturday:\r\n        return \"Weekend\";\r\n    case DayOfWeek.Sunday:\r\n        return \"Weekend\";\r\n    default:\r\n        throw new ArgumentOutOfRangeException();\r\n}<\/pre>\n<p>As we can see, we have to write a lot of code. We can compact this further by joining all of the <code>case<\/code> statements that return the same result:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">switch (DateTime.Now.DayOfWeek)\r\n{\r\n    case DayOfWeek.Monday:\r\n    case DayOfWeek.Tuesday:\r\n    case DayOfWeek.Wednesday:\r\n    case DayOfWeek.Thursday:\r\n    case DayOfWeek.Friday:\r\n        return \"Not Weekend\";\r\n    case DayOfWeek.Saturday:\r\n    case DayOfWeek.Sunday:\r\n        return \"Weekend\";\r\n    default:\r\n        throw new ArgumentOutOfRangeException();\r\n}<\/pre>\n<p>That\u2019s a little better, wouldn\u2019t you agree? But we can do even better than this!<\/p>\n<p>Beginning with C# 8, switch expressions were introduced to help us reduce the amount of code we have to write even more.<\/p>\n<p>Let\u2019s transform the previous switch statement into a switch expression:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">DateTime.Now.DayOfWeek switch\r\n{\r\n    DayOfWeek.Monday =&gt; \"Not Weekend\",\r\n    DayOfWeek.Tuesday =&gt; \"Not Weekend\",\r\n    DayOfWeek.Wednesday =&gt; \"Not Weekend\",\r\n    DayOfWeek.Thursday =&gt; \"Not Weekend\",\r\n    DayOfWeek.Friday =&gt; \"Not Weekend\",\r\n    DayOfWeek.Saturday =&gt; \"Weekend\",\r\n    DayOfWeek.Sunday  =&gt; \"Weekend\",\r\n    _ =&gt; throw new ArgumentOutOfRangeException()\r\n}\r\n<\/pre>\n<p>As we can see, it\u2019s much more concise and readable than before. So are we finished now? Almost.<\/p>\n<p>Starting with C# 9, we can also use logical patterns in our switch expressions. The <code>or<\/code> logical pattern fits nicely with what we are trying to achieve:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">DateTime.Now.DayOfWeek switch\r\n{\r\n    DayOfWeek.Monday or DayOfWeek.Tuesday or DayOfWeek.Wednesday or DayOfWeek.Thursday or DayOfWeek.Friday =&gt; \"Not Weekend\",\r\n    DayOfWeek.Saturday or DayOfWeek.Sunday =&gt; \"Weekend\",\r\n    _ =&gt; throw new ArgumentOutOfRangeException()\r\n}<\/pre>\n<p>One last optimization we can introduce is to use the negation logical pattern <code>not<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">DateTime.Now.DayOfWeek switch\r\n{\r\n    not (DayOfWeek.Saturday or DayOfWeek.Sunday) =&gt; \"Not Weekend\",\r\n    DayOfWeek.Saturday or DayOfWeek.Sunday =&gt; \"Weekend\",\r\n    _ =&gt; throw new ArgumentOutOfRangeException()\r\n}<\/pre>\n<h2 id=\"the-proper-way-to-rethrow-exceptions\">The Proper Way to Rethrow Exceptions<\/h2>\n<p>Exception handling is a very important aspect of our code. We can often see one pattern repeated through the codebase is catching an exception, handling it locally, and then rethrowing it to a higher-level component.<\/p>\n<p>The rethrowing step is where we can easily make a mistake:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">try\r\n{\r\n    await GetBlogsFromApi();\r\n}\r\ncatch (HttpRequestException e)\r\n{\r\n    throw e;\r\n}<\/pre>\n<p>Do you know what is the problem when we rethrow an exception like this?<\/p>\n<p>The stack trace of the exception gets rewritten to the line of code where we explicitly rethrow it. This means that we lose all of the valuable information about what caused the exception in the first place. This can make debugging the code very hard.<\/p>\n<p>However, we can fix this very easily:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">try\r\n{\r\n    await GetBlogsFromApi();\r\n}\r\ncatch (HttpRequestException e)\r\n{\r\n    throw;\r\n}\r\n<\/pre>\n<p>When we do it like this, the exception is rethrown while preserving the original stack trace. We are now saving all of that valuable information about what caused the exception in the first place. It will be much easier for us to debug the code, and figure out what the problem is.<\/p>\n<h2 id=\"how-to-filter-exceptions\">How to Filter Exceptions<\/h2>\n<p>Do you have a situation in your code where you need to handle a specific exception multiple times? We often encounter a case like this, where we have to perform different exception handling logic based on some condition.<\/p>\n<p>Let us say we want to handle an <code>HttpRequestException<\/code> in one way when the <code>StatusCode<\/code> is <code>400<\/code> (Bad Request), and in another way when the <code>StatusCode<\/code> is <code>404<\/code> (Not Found). The naive approach would be to catch the exception and then write an if-statement to check a condition:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">try\r\n{\r\n    await GetBlogsFromApi();\r\n}\r\ncatch (HttpRequestException e)\r\n{\r\n    if (e.StatusCode == HttpStatusCode.BadRequest)\r\n    {\r\n        HandleBadRequest(e);\r\n    }\r\n    else if (e.StatusCode == HttpStatusCode.NotFound)\r\n    {\r\n        HandleNotFound(e);\r\n    }\r\n}\r\n<\/pre>\n<p>Although this works, it\u2019s not the cleanest approach. There is a much better solution that you might not know about.<\/p>\n<p>Here is how we can elegantly catch the same exception based on a certain condition:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">try\r\n{\r\n    await GetBlogsFromApi();\r\n}\r\ncatch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.BadRequest)\r\n{\r\n    HandleBadRequest(e);\r\n}\r\ncatch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.NotFound)\r\n{\r\n    HandleNotFound(e);\r\n}<\/pre>\n<p>This approach is much cleaner and easier to extend when we need to add more conditions.<\/p>\n<h2 id=\"why-you-should-use-records-as-data-transfer-objects\">Why You Should Use Records as Data Transfer Objects<\/h2>\n<p>Beginning with C# version 9, the long-awaited <code>record<\/code> types feature was introduced. Records are reference types, just like classes. However, records have an amazing feature that classes don\u2019t &#8211; they are immutable by default.<\/p>\n<p>Here is how we can define a simple record:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public record ProductDto(string Id, string Name, string Category, decimal Price);\r\n<\/pre>\n<p>When defined like this, it is called a &#8220;Positional record&#8221;. We can also define the same record like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public record ProductDto\r\n{\r\n    public string Id { get; init; }\r\n\r\n    public string Name { get; init; }\r\n\r\n    public string Category { get; init; }\r\n\r\n    public decimal Price { get; init; }\r\n}\r\n<\/pre>\n<p>The new <code>init<\/code> setter allows the value of the property to be set only once when the object instance is created. After that, it can no longer be modified, thus ensuring immutability.<\/p>\n<p>Positional records are a great candidate for Data Transfer Objects (DTOs) because they are immutable and very simple to define. When replacing classes with records for DTOs, you will find that the amount of code in your codebase will drastically reduce.<\/p>\n<h2 id=\"the-proper-way-to-return-empty-collections\">The Proper Way to Return Empty Collections<\/h2>\n<p>Often, we have methods that return a collection. We perform some validation beforehand, then populate the collection and return it. However, what should we return in case the preconditions are not met?<\/p>\n<p>One option is to return <code>null<\/code> values:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">IEnumerable&lt;Product&gt; GetProductsByCategory(string category)\r\n{\r\n    if (string.IsNullOrWhiteSpace(category))\r\n    {\r\n        return null;\r\n    }\r\n\r\n    var products = _dbContext.Products.Where(p =&gt; p.Category == category).ToList();\r\n\r\n    return products;\r\n}<\/pre>\n<p>This is generally a bad practice because we now force the calling code to check the <code>null<\/code> result.<\/p>\n<p>A better approach would be to just return an empty collection:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"5\">IEnumerable&lt;Product&gt; GetProductsByCategory(string category)\r\n{\r\n    if (string.IsNullOrWhiteSpace(category))\r\n    {\r\n        return new List&lt;Product&gt;();\r\n    }\r\n\r\n    var products = _dbContext.Products.Where(p =&gt; p.Category == category).ToList();\r\n\r\n    return products;\r\n}\r\n<\/pre>\n<p>Although this approach is fine, we can achieve the same result with a cleaner approach:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"5\">IEnumerable&lt;Product&gt; GetProductsByCategory(string category)\r\n{\r\n    if (string.IsNullOrWhiteSpace(category))\r\n    {\r\n        return Enumerable.Empty&lt;Product&gt;();\r\n    }\r\n\r\n    var products = _dbContext.Products.Where(p =&gt; p.Category == category).ToList();\r\n\r\n    return products;\r\n}\r\n<\/pre>\n<p>Using <code>Array.Empty<\/code> and <code>Enumerable.Empty<\/code> is the preferred way for returning an empty collection from a method. This is because every time you instantiate an empty array or list, it is stored in memory. This increases the pressure on the Garbage Collector. However, when we use <code>Array.Empty<\/code> or <code>Enumerable.Empty<\/code> there is only one instance of an empty collection that is created, which is reusable. This will reduce the memory consumption of our application.<\/p>\n<h2 id=\"make-your-code-robust-with-readonly-collections\">C# Tips to Make Your Code Robust With Readonly Collections<\/h2>\n<p>Let\u2019s create a simple <code>Writer<\/code> class, with a collection of blogs:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class Writer\r\n{\r\n    public Writer(string name, List&lt;Blog&gt; blogs)\r\n    {\r\n        Name = name;\r\n        Blogs = blogs;\r\n    }\r\n\r\n    public string Name { get; set; }\r\n\r\n    public List&lt;Blog&gt; Blogs { get; set; }\r\n}<\/pre>\n<p>What is preventing us from adding or removing blogs from the <code>Blogs<\/code> collection?<\/p>\n<p>With this approach nothing. Our <code>Writer<\/code> class has no encapsulation. Someone could manipulate a <code>Writer<\/code> instance as they wish:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var writer = new Writer(\u201cCode Maze\u201d, new List&lt;Blog&gt;());\r\n\r\nwriter.Blogs.Add(blog1);\r\n\r\nwriter.Blogs.Remove(blog2);\r\n<\/pre>\n<p>Clearly, we can\u2019t allow this much freedom to our consumers. We will enforce encapsulation by creating a private field for storing the blogs. Let\u2019s modify the <code>Writer<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"3, 8, 13\">public class Writer\r\n{\r\n    private List&lt;Blog&gt; _blogs = new List&lt;Blog&gt;();\r\n\r\n    public Writer(string name, List&lt;Blog&gt; blogs)\r\n    {\r\n        Name = name;\r\n        _blogs = blogs;\r\n    }\r\n\r\n    public string Name { get; set; }\r\n\r\n    public List&lt;Blog&gt; Blogs =&gt; _blogs;\r\n}\r\n<\/pre>\n<p>This implementation is a little better, but we still have the same issue as before. Nothing is preventing our consumers from manipulating the <code>Blogs<\/code> collection.<\/p>\n<p>To completely close the <code>Blogs<\/code> collection from modification we can use one of the read-only collection interfaces. We can use either <code>IReadonlyCollection<\/code> or <code>IReadonlyList<\/code>. Let\u2019s go with <code>IReadonlyCollection<\/code> and modify the <code>Writer<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"13\">public class Writer\r\n{\r\n    private List&lt;Blog&gt; _blogs = new List&lt;Blog&gt;();\r\n\r\n    public Writer(string name, List&lt;Blog&gt; blogs)\r\n    {\r\n        Name = name;\r\n        _blogs = blogs;\r\n    }\r\n\r\n    public string Name { get; set; }\r\n\r\n    public IReadonlyCollection&lt;Blog&gt; Blogs =&gt; _blogs;\r\n}\r\n<\/pre>\n<p>Great, we have almost completely encapsulated the <code>Writer<\/code> class.<\/p>\n<p>The previous code no longer works:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var writer = new Writer(\u201cCode Maze\u201d, new List&lt;Blog&gt;());\r\n\r\nwriter.Blogs.Add(blog1); \/\/ Compiler error.\r\n\r\nwriter.Blogs.Remove(blog2); \/\/ Compiler error.\r\n<\/pre>\n<p>This is because the <code>IReadonlyCollection<\/code> interface doesn\u2019t contain methods for altering the collection.<\/p>\n<p>However, nothing is preventing our consumers from doing this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var writer = new Writer(\u201cCode Maze\u201d, new List&lt;Blog&gt;());\r\n\r\n(writer.Blogs as List&lt;Blog&gt;).Add(blog1);\r\n<\/pre>\n<p>Luckily, the fix for this is simple. We will just return a new collection instance in our <code>Writer<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"13\">public class Writer\r\n{\r\n    private List&lt;Blog&gt; _blogs = new List&lt;Blog&gt;();\r\n\r\n    public Writer(string name, List&lt;Blog&gt; blogs)\r\n    {\r\n        Name = name;\r\n        _blogs = blogs;\r\n    }\r\n\r\n    public string Name { get; set; }\r\n\r\n    public IReadonlyCollection&lt;Blog&gt; Blogs =&gt; _blogs.AsReadonly();\r\n}\r\n<\/pre>\n<p>Now we completely encapsulate the <code>Writer<\/code> class and make our code much more robust.<\/p>\n<h2 id=\"use-the-memory-locality-principle-for-better-performance\">Use the Memory Locality Principle For Better Performance<\/h2>\n<p>In computer science, the principle of locality is the tendency of a processor to access the same set of memory locations over a short period. In such cases, there are optimization techniques that can be applied to improve performance. For example, memory prefetching is an example of an optimization where we prefetch subsequent memory locations before we even need to access them.<\/p>\n<p>Enough with the technical details. Let us see how we can use this to improve performance.<\/p>\n<p>We will look at two examples where we are iterating over a matrix, and counting how many elements are greater than zero. For simplicity, let\u2019s assume we have an array of arrays, and the size is 5000&#215;5000:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">for (int i = 0; i &lt; matrix.Length; i++)\r\n{\r\n    for (int j = 0; j &lt; matrix.Length; j++)\r\n    {\r\n        if (matrix[i][j] &gt; 0)\r\n        {\r\n            result++;\r\n        }\r\n    }\r\n}<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">for (int i = 0; i &lt; matrix.Length; i++)\r\n{\r\n    for (int j = 0; j &lt; matrix.Length; j++)\r\n    {\r\n        if (matrix[j][i] &gt; 0)\r\n        {\r\n            result++;\r\n        }\r\n    }\r\n}<\/pre>\n<p>What do you think, which algorithm will perform faster?<\/p>\n<p>If you guessed the first one, you are correct. Here are the benchmark results on our machine:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/benchmark_results_final.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-58645\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/benchmark_results_final.png\" alt=\"Benchmark result displaying useful C# Tip to improve performance. \" width=\"690\" height=\"226\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/benchmark_results_final.png 990w, https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/benchmark_results_final-300x98.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/benchmark_results_final-768x251.png 768w\" sizes=\"auto, (max-width: 690px) 100vw, 690px\" \/><\/a><\/p>\n<p>However, we should understand why this is the case. Arrays and matrices (arrays of arrays) are stored sequentially in memory. Matrices are actually stored row-first. This means that we will be accessing subsequent memory locations when we are accessing the matrix data row by row. That is how we can benefit from the memory locality principle, and gain improved performance.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>There we go! We&#8217;ve learned 11 useful C# tips for how to improve the quality of our code and increase performance.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we are going to learn some useful C# tips on how to improve our code quality and performance.\u00a0 Let\u2019s get started! Why These C# Tips? Before we begin, let us briefly discuss why we chose these specific C# tips over many others that certainly exist. With these tips, we can achieve a [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":58683,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[12,2134],"tags":[10,22,914,915,913],"class_list":["post-58644","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-csharp","category-performance","tag-net","tag-net-core","tag-code-quality","tag-coding-standards","tag-performance","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Top 11 C# Tips to Improve Code Quality and Performance -<\/title>\n<meta name=\"description\" content=\"Find out how to improve C# code quality and performance with our carefully chosen tips. You will learn how to apply the latest C# features.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Top 11 C# Tips to Improve Code Quality and Performance -\" \/>\n<meta property=\"og:description\" content=\"Find out how to improve C# code quality and performance with our carefully chosen tips. You will learn how to apply the latest C# features.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2021-07-12T06:00:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-03-22T11:21:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Code Maze\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/CodeMazeBlog\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Code Maze\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/\"},\"author\":{\"name\":\"Code Maze\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04\"},\"headline\":\"Top 11 C# Tips to Improve Code Quality and Performance\",\"datePublished\":\"2021-07-12T06:00:21+00:00\",\"dateModified\":\"2024-03-22T11:21:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/\"},\"wordCount\":2106,\"commentCount\":14,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png\",\"keywords\":[\".NET\",\".NET CORE\",\"Code Quality\",\"Coding Standards\",\"Performance\"],\"articleSection\":[\"C#\",\"Performance\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/\",\"url\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/\",\"name\":\"Top 11 C# Tips to Improve Code Quality and Performance -\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png\",\"datePublished\":\"2021-07-12T06:00:21+00:00\",\"dateModified\":\"2024-03-22T11:21:48+00:00\",\"description\":\"Find out how to improve C# code quality and performance with our carefully chosen tips. You will learn how to apply the latest C# features.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png\",\"width\":1100,\"height\":620,\"caption\":\"C# Tips Featured Image\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Top 11 C# Tips to Improve Code Quality and Performance\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04\",\"name\":\"Code Maze\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png\",\"caption\":\"Code Maze\"},\"description\":\"This is the standard author on the site. Most articles are published by individual authors, with their profiles, but when several authors have contributed, we publish collectively as a part of this profile.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/company\/codemaze\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog\"],\"url\":\"https:\/\/code-maze.com\/author\/codemazecontributor\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Top 11 C# Tips to Improve Code Quality and Performance -","description":"Find out how to improve C# code quality and performance with our carefully chosen tips. You will learn how to apply the latest C# features.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/","og_locale":"en_US","og_type":"article","og_title":"Top 11 C# Tips to Improve Code Quality and Performance -","og_description":"Find out how to improve C# code quality and performance with our carefully chosen tips. You will learn how to apply the latest C# features.","og_url":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/","og_site_name":"Code Maze","article_published_time":"2021-07-12T06:00:21+00:00","article_modified_time":"2024-03-22T11:21:48+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png","type":"image\/png"}],"author":"Code Maze","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/CodeMazeBlog","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Code Maze","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/"},"author":{"name":"Code Maze","@id":"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04"},"headline":"Top 11 C# Tips to Improve Code Quality and Performance","datePublished":"2021-07-12T06:00:21+00:00","dateModified":"2024-03-22T11:21:48+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/"},"wordCount":2106,"commentCount":14,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png","keywords":[".NET",".NET CORE","Code Quality","Coding Standards","Performance"],"articleSection":["C#","Performance"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/","url":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/","name":"Top 11 C# Tips to Improve Code Quality and Performance -","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png","datePublished":"2021-07-12T06:00:21+00:00","dateModified":"2024-03-22T11:21:48+00:00","description":"Find out how to improve C# code quality and performance with our carefully chosen tips. You will learn how to apply the latest C# features.","breadcrumb":{"@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/07\/C-Tips.png","width":1100,"height":620,"caption":"C# Tips Featured Image"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/csharp-tips-improve-quality-performance\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"Top 11 C# Tips to Improve Code Quality and Performance"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04","name":"Code Maze","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png","caption":"Code Maze"},"description":"This is the standard author on the site. Most articles are published by individual authors, with their profiles, but when several authors have contributed, we publish collectively as a part of this profile.","sameAs":["https:\/\/www.linkedin.com\/company\/codemaze\/","https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog"],"url":"https:\/\/code-maze.com\/author\/codemazecontributor\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/58644","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=58644"}],"version-history":[{"count":29,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/58644\/revisions"}],"predecessor-version":[{"id":75488,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/58644\/revisions\/75488"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/58683"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=58644"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=58644"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=58644"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}