# DRY Code in C#

When several classes repeat the same properties and methods, the code breaks the DRY rule (Don't Repeat Yourself). One class that does everything isn't the answer either.

Novice · C# · OOP · Updated November 3, 2026

## After this lesson you can

- Spot code that repeats itself across classes, and explain why one class for everything is no fix

## Key takeaways

- DRY means Don't Repeat Yourself. Code repeated across classes has to be changed in every copy, and missing one is a bug.
- Merging every kind into one class with a `Type` property is no fix: objects carry properties they never use, and every method fills up with `if`s.
- A good class is cohesive: it has one clear job. One `Character` class that is every kind of character at once has four.

With **encapsulation**, you group related data and methods into classes, each with a clear job. But as you write more classes, you'll notice some of them look very alike: the same properties, the same methods, sometimes the same code inside them.

When that happens, your code breaks the **DRY** rule: *Don't Repeat Yourself*.

## An adventure game

Say you're writing an adventure game with three kinds of character: an **archer**, a **wizard** and a **knight**. Here's how the classes look:

![Character, Archer, Wizard and Knight classes, with most properties and methods in common](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/09/5b7375a11ea944f5b94a7877414e6199.png "Character, Archer, Wizard and Knight classes, with most properties and methods in common")

(Class diagrams like these usually write names in lower case: `levelUp()` here is `LevelUp()` in C#.)

Every character has a name, health, a level and experience. Every character can attack, take damage and level up. The parts in red belong to one kind only: an archer's arrows, a wizard's mana, a knight's armor. The methods in blue work a little differently for that kind of character.

In code, the repetition looks like this:

```csharp
Archer archer = new Archer { Name = "Robin", Health = 100 };
Wizard wizard = new Wizard { Name = "Merlin", Health = 80 };

archer.LevelUp();
wizard.LevelUp();
Console.WriteLine($"{archer.Name}: level {archer.Level}, health {archer.Health}");
Console.WriteLine($"{wizard.Name}: level {wizard.Level}, health {wizard.Health}");

public class Archer
{
    public string Name { get; set; } = "";
    public int Health { get; set; }
    public int Level { get; set; } = 1;
    public int Arrows { get; set; }

    public void LevelUp()
    {
        Level++;
        Health += 10;
    }
}

public class Wizard
{
    public string Name { get; set; } = "";
    public int Health { get; set; }
    public int Level { get; set; } = 1;
    public int Mana { get; set; }

    public void LevelUp()
    {
        Level++;
        Health += 10;
    }
}
```

```text
Robin: level 2, health 110
Merlin: level 2, health 90
```

Two classes, and already `Name`, `Health`, `Level` and `LevelUp` are written twice. Add a knight and they're written three times. Now imagine leveling up should add 15 health instead of 10: you'd have to find and change every copy, and missing one is a bug.

## One class for everything?

One way to remove the repetition is to merge every kind of character into one class:

![One Character class with a type, plus arrows, mana and armor for every character](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/09/75ceeaabf7f5429ebcf1affe88f1c5de.png "One Character class with a type, plus arrows, mana and armor for every character")

- A `Type` property says which kind of character it is.
- `Arrows` is only used by archers, `Mana` only by wizards, `Armor` only by knights.
- Methods that differ by kind need `if` statements inside: *if the type is archer, do this; if it's a wizard, do that.*

The repetition is gone, but this is a **bad solution**:

- **Every character carries properties it never uses.** A knight has arrows and mana, always zero.
- **Every method is a tangle of ifs.** Adding a fourth kind of character means changing every one of them.
- **The class isn't cohesive any more.** It no longer has one clear job; it has four.

The next lessons show the right tool: **inheritance**, which puts the shared parts in one class and keeps each kind's own parts in its own class.

## Check yourself

1 question to try on the lesson page.

## So what

Repeated code means repeated bugs, and one giant class means tangled code. Spotting both is the first step toward inheritance, which fixes the repetition without the tangle.

## Key terms

- [DRY Principle](https://www.ask-codey.com/glossary/dry-principle)
- [Cohesion](https://www.ask-codey.com/glossary/cohesion)

## Cheat sheets

- [DRY Code in C#](https://www.ask-codey.com/cheat-sheets/dry-code-in-csharp-cheat-sheet)

Source: https://www.ask-codey.com/lessons/dry-code-in-csharp
