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
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
Typeproperty is no fix: objects carry properties they never use, and every method fills up withifs. - A good class is cohesive: it has one clear job. One
Characterclass 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:

(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:
Archer archer = new Archer { Name = "Robin", Health = 100 };
Wizard wizard = new Wizard { Name = "Merlin", Health = 80 };
archer.LevelUp();
wizard.LevelUp();
Console.WriteLine( quot;{archer.Name}: level {archer.Level}, health {archer.Health}");
Console.WriteLine( quot;{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;
}
}
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:

- A
Typeproperty says which kind of character it is. Arrowsis only used by archers,Manaonly by wizards,Armoronly by knights.- Methods that differ by kind need
ifstatements 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.