Linus Torvalds’ Rules of Programming Applied to C#

Clean, efficient, and pragmatic code

Posted by Rodrigo Castro on July 4, 2025

Linus Torvalds, creator of Linux and Git, is known for his blunt wisdom about writing good code. Though his advice emerged from systems programming in C, many of his principles remain highly relevant in high-level languages like C#. Let’s explore how his rules translate to C#, with examples of what to DO and what NOT to DO.

🧠 “Talk is cheap. Show me the code.”

DO: Deliver working, understandable code.

1
2
// DO: Keep it simple and functional
public int Add(int a, int b) => a + b;

DON’T: Add layers before you even need them.

1
2
3
4
5
6
// NOT-DO: Premature abstraction
public interface IAdder { int Add(int a, int b); }
public class FancyAdder : IAdder
{
    public int Add(int a, int b) => a + b;
}

📊 “Bad programmers worry about code. Good programmers worry about data structures and their relationships.”

DO: Think about how your data is organized and flows.

1
2
3
4
5
public class Order
{
    public List<OrderItem> Items { get; set; }
    public decimal Total => Items.Sum(i => i.Price * i.Quantity);
}

DON’T: Ignore structure and rely on parallel lists.

1
2
3
4
5
6
public class OrderBad
{
    public List<string> ProductNames { get; set; }
    public List<decimal> Prices { get; set; }
    public List<int> Quantities { get; set; }
}

📉 “If you need more than 3 levels of indentation, you’re screwed anyway.”

DO: Use early returns and extract methods.

1
2
3
4
5
6
7
public void Process(User user)
{
    if (!user.IsActive) return;
    if (!user.HasPermission("admin")) return;

    DoSomething(user);
}

DON’T: Nest deeply.

1
2
3
4
5
6
7
8
9
10
public void Process(User user)
{
    if (user.IsActive)
    {
        if (user.HasPermission("admin"))
        {
            DoSomething(user);
        }
    }
}

📝 “Comment only what the code cannot say.”

DO: Write expressive code and document intent, not mechanics.

1
2
3
4
5
6
7
public decimal CalculateDiscount(Customer customer)
{
    if (customer.IsVip)
        return 0.2m;

    return 0.05m;
}

DON’T: Add redundant comments.

1
2
3
4
5
6
// Check if customer is VIP
if (customer.IsVip)
{
    // Return 20% discount
    return 0.2m;
}

⚖️ “Don’t add complexity unless you must.”

DO: Start simple and refactor when needed.

1
2
3
4
public string FormatName(string firstName, string lastName)
{
    return $"{firstName} {lastName}";
}

DON’T: Create layers or patterns prematurely.

1
2
3
4
5
6
7
public class NameFormatter
{
    public string Format(Name name)
    {
        return $"{name.First} {name.Last}";
    }
}

🧪 “I don’t use debuggers. I use my brain.”

DO: Think through your code and use logs or tests to narrow down issues.

1
2
// DO: Use logs to trace
_logger.LogDebug("Processing user with ID: {UserId}", user.Id);

DON’T: Rely solely on step-by-step debugging to understand logic.

1
// NOT-DO: Insert breakpoints everywhere and hope to understand later

🙈 “Clever code is often broken code.”

DO: Write code that’s obvious to the next developer.

1
2
3
// DO: Descriptive and simple
public bool IsWeekend(DateTime date) =>
    date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;

DON’T: Try to impress with one-liners

1
2
// NOT-DO: Obfuscated logic
public bool IsWeekend(DateTime d) => ((int)d.DayOfWeek & 6) != 0;

👥 “Write code for humans, not for the compiler.”

DO: Optimize for readability, not micro-performance.

1
2
// DO: Descriptive naming, clear logic
public bool IsUserEligible(User user) => user.IsActive && user.HasPaid;

DON’T: Obsess over premature optimizations

1
2
// NOT-DO: Cryptic logic to save milliseconds
bool f(User u) => u.a && u.b;

🙃 “If you think your users are idiots, only idiots will use it.”

DO: Respect your users. Build helpful APIs and messages.

1
2
// DO: Clear validation message
throw new ArgumentException("Username must be at least 6 characters.");

DON’T: Be cryptic or unhelpful

1
2
// NOT-DO: Vague message
throw new Exception("Invalid input.");

🔁 “Don’t rewrite everything from scratch.”

DO: Refactor gradually, improving existing code when possible.

1
2
// DO: Improve method incrementally
public void SendEmail(User user) { /* new logic here */ }

DON’T: Burn everything down

1
// NOT-DO: Rewrite the entire service just to change one dependency

By embracing these final rules from Linus’ philosophy, we keep our C# code simple, respectful, and robust. Write for the next developer, not for your ego.