Skip to footer content
Iron Academy Logo
Learn C#
Learn C#

Other Categories

14 Ways to Simplify Your C# Code – Insights on C# Best Practices from Tim Corey's Video

Tim Corey
44m 57s

In his comprehensive video "14 Ways to Simplify Your C# Code," Tim Corey explores practical C# best practices that improve code readability, reduce clutter, and keep your code base maintainable. Rather than obsessing over one-liners or cryptic tricks, Tim focuses on good coding practices—how to write clean, understandable code that other developers can follow.

He frames each tip around real examples in Visual Studio, touching on naming conventions, error handling, and even how to refactor code without breaking things. This isn’t just theory—it’s about practice makes code better.

In this article, let’s walk through each of the 14 ways he demonstrated.

1. Static Using for Cleaner Code

Tim begins by showing how static access can simplify repetitive calls. By declaring:

using static System.Console;
using static System.Console;

you no longer need to prefix every static member with Console..

This is more than just removing words—it’s about making static access clear. Tim points out that if you’re calling a static member defined in a frequently used class like Console or Math, this shorthand improves code readability.

However, as part of good coding practices, he warns that developers should avoid conflicts—two different classes might have the same name for a static member. Awareness of potential unexpected behavior is key.

2. List Initialization with

C# now lets you initialize lists more directly:

List<string> names = ["Tim", "Sue", "Bilbo"];
List<string> names = ["Tim", "Sue", "Bilbo"];

Tim explains that this isn’t about squeezing everything into only one statement—it’s about writing code that’s easier to read and optimize performance by reducing ceremony.

Instead of parsing out the “new List of String” boilerplate, the reader sees exactly what matters: the descriptive names in the collection. Tim also notes this works for arrays and even dictionaries, aligning with coding conventions that prioritize clarity.

3. Target-Typed new

Another time-saver: target-typed new. Instead of:

List<int> numbers = new List<int>();
List<int> numbers = new List<int>();

you can write:

List<int> numbers = new();
List<int> numbers = new();

Tim highlights that repeating the class name is unnecessary—it’s already on the left side. This follows good coding practices by removing redundancy while keeping your code base easier to scan.

4. var and Anonymous Types

Tim tackles var, a feature that sparks debate among coding practices circles. Some dislike it for hiding variable names and types, but Tim clarifies that its real power lies in anonymous types.

When working with data sources (like SQL via Dapper), Tim shows how var lets you create objects on the fly:

var parameters = new { FirstName = "Tim", LastName = "Corey" };
var parameters = new { FirstName = "Tim", LastName = "Corey" };

This is perfect for write queries or one-off objects—you don’t need to create a base class just for parameters. As Tim says, this avoids polluting your code base with unnecessary types, while still providing meaningful error messages if something goes wrong.

5. File-Scoped Namespaces

Tim moves to file-scoped namespaces, showing how this:

namespace ProjectName
{
    // indented code
}
namespace ProjectName
{
    // indented code
}

becomes this:

namespace ProjectName;
namespace ProjectName;

This small change eliminates wasted indentation and adheres to C# naming conventions like Pascal casing for public members. Tim explains that since most files contain just one namespace, this improves code readability and keeps logical sections aligned.

6. Records for One-Line Data Structures

Using records lets you define data objects in only one statement:

public record EmployeeRecord(int Id, string Name);
public record EmployeeRecord(int Id, string Name);

Tim notes that this generates a full type—properties, immutability, and ToString()—with minimal effort. He’s clear that derived class scenarios still require classes, but when your object is read-only, records follow the single responsibility principle by doing one job well.

7. Pattern Matching

Tim demonstrates how pattern matching helps you handle exceptions and perform comparisons safely. Instead of writing verbose type checks, you can combine them:

if (emp is EmployeeRecord e)
{
    e.Id = 1;
}
if (emp is EmployeeRecord e)
{
    e.Id = 1;
}

This single line checks and casts. Tim says this aligns with good coding practices—you avoid single letter variable names like x or y and instead give descriptive names like e. Clear method names and variable names make code easier for other developers to maintain.

8. String Interpolation

For building readable strings, Tim demonstrates string interpolation:

$"The employee with ID {e.Id} is {e.Name}"
$"The employee with ID {e.Id} is {e.Name}"

He points out that this makes meaningful error messages and write comments easier. Instead of tangled concatenation, you can literally write code that reads like English—improving code quality and simplifying future unit tests that check output.

9. nameof() for Safe Refactoring

Tim shows how nameof() protects you when you refactor code. Hard-coded variable names in strings can lead to unexpected behavior if renamed. But by writing:

nameof(emp)
nameof(emp)

the compiler updates every usage automatically. This is one of those best practices that keeps your code base healthy when you write clean and reorganize code.

10. Tuples for Multiple Return Values

Instead of creating a base class just to return two values, Tim uses tuples:

(string FirstName, string LastName) SplitName(string fullName)
(string FirstName, string LastName) SplitName(string fullName)

This avoids unnecessary external dependencies and adheres to single responsibility principle—the method just splits a name, nothing more. As Tim says, practice makes code better when you avoid over-engineering.

11. Deconstruction

Building on tuples, Tim shows how to deconstruct results into local variables:

var (firstName, lastName) = SplitName("Tim Corey");
var (firstName, lastName) = SplitName("Tim Corey");

This keeps variable names descriptive and avoids cryptic tuple syntax later. Tim even touches on discarding unused values (using _), which signals intent—no single letter variable names left unexplained.

12. Discards for Unneeded Values

If you don’t need all tuple parts, Tim recommends discards:

var (firstName, _) = SplitName("Tim Corey");
var (firstName, _) = SplitName("Tim Corey");

This shows other developers you’re intentionally ignoring a value—good for testing frameworks or unit tests where not all outputs matter.

13. using Statements Without Blocks

Tim moves into resource management and error handling. Previously, you’d write:

using (var connection = new SqlConnection(connString))
{
    // work
}
using (var connection = new SqlConnection(connString))
{
    // work
}

Now, you can use:

using var connection = new SqlConnection(connString);
using var connection = new SqlConnection(connString);

This aligns with SOLID principles—specifically the single responsibility principle and dependency inversion principle. Tim notes that this syntax works well for external dependencies like databases, ensuring most exception handling is cleaner and connections always close, avoiding performance issues or even SQL injection scenarios when connections aren’t disposed.

14. Inline out Variable Declarations

Finally, Tim covers inline out variable declarations for things like parsing:

if (int.TryParse(numberText, out int numberValue))
if (int.TryParse(numberText, out int numberValue))

Here, you create the local variable in the same line. This keeps coding conventions tight and method names descriptive. By keeping code properly grouped, you reduce unexpected behavior and make future refactor code efforts safer.

Wrapping Up

Tim closes by his video by reminding viewers: these simplifications aren’t about writing cryptic one-liners—they’re about good coding practices. Features like using static, records, pattern matching, tuples, and discards let you write clean, modern C#.

He encourages developers to think about naming conventions, error handling, and meaningful names as they adopt these features. “Code is meant to be read by humans,” Tim says—and when you write code that’s easy to understand, you make life better for yourself and other developers.

In short: embrace these C# best practices, follow SOLID principles like the single responsibility principle, interface segregation principle, and dependency inversion principle, and your code will not just compile—it will improve performance, reduce unexpected behavior, and keep your team happy coding.

Hero Worlddot related to 14 Ways to Simplify Your C# Code – Insights on C# Best Practices from Tim Corey's Video
Hero Affiliate related to 14 Ways to Simplify Your C# Code – Insights on C# Best Practices from Tim Corey's Video

Earn More by Sharing What You Love

Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!