CodeGym /Courses /C# SELF /Common Mistakes When Declaring Classes and Objects

Common Mistakes When Declaring Classes and Objects

C# SELF
Level 25 , Lesson 0
Available

1. Name Clash Problem: Field, Property, Parameter

Newbies often run into situations where property names, constructor parameters, and private fields have the same name. The compiler won't complain, but the result might not be what you expect.

Example

public class Student
{
    private string name;

    public Student(string name)
    {
        name = name; // "Seems legit..."
    }

    public void PrintName()
    {
        Console.WriteLine(name);
    }
}

So what happens? The PrintName() method has nothing to print: the private field name will stay null! That's because inside the constructor, name = name; works with the local parameter, not the class field.

How to avoid it

Use the this keyword to refer to class fields/properties:

public Student(string name)
{
    this.name = name; // Now it's all good!
}

Note: Rider and other IDEs will help you spot these mistakes — don't ignore their hints!

2. Missing Default Constructor: When Do You Need It?

If you declare at least one custom constructor, the compiler won't create an "empty" default constructor for you anymore. This often leads to errors, especially when you try to create an object without parameters.

Example

public class Book
{
    public string Title { get; set; }

    // Explicitly declared constructor
    public Book(string title)
    {
        Title = title;
    }
}

var book = new Book(); // Compiler: "Beep-beep! No parameterless constructor!"

If you want to create an instance both with and without parameters, don't forget to explicitly add the needed constructor:

public Book() { }

public Book(string title)
{
    Title = title;
}

3. Access Modifiers: The Private Life of Public People

A common rookie mistake is not thinking about access modifiers. By default, class fields and methods have the private modifier, and struct members are also private. Forgetting or not specifying can make it impossible to use the needed properties or methods outside the class.

Example

public class Animal
{
    string name; // private by default

    public void PrintName()
    {
        Console.WriteLine(name);
    }
}

var animal = new Animal();
animal.name = "Fluffy"; // Compilation error!

The compiler won't let you access a private member. It's better to explicitly specify the modifier:

public string Name;

or

private string name;

For smarter access, use properties:

public string Name { get; set; }

4. Forgot to Initialize a Field: The null Trap

A super common trap — a class field isn't initialized. This is especially important if the field will be used in methods called before explicit initialization.

Example

public class Cat
{
    public string Name;

    public void SayHello()
    {
        Console.WriteLine($"Meow! Name length is {Name.Length} letters!"); // Possible NullReferenceException
    }
}

var cat = new Cat();
cat.SayHello(); // What a tragedy!

The variable Name is null, and trying to access Length will throw a NullReferenceException. Always keep an eye on object state after creation!

Tip: Use constructors to require important fields, and mark properties as required (in new C# - with required).

5. Infinite Recursion in Auto-Properties: Copy-Paste Fail

Sometimes you write a property by hand and mess up — for example, inside the getter or setter you refer to the property itself (not the private field), which leads to an endless loop.

Example

public class Dog
{
    public int Age
    {
        get { return Age; } // Oops!
        set { Age = value; } // Double oops!
    }
}

This code, whenever you call Age, will call itself... forever (until the stack blows up — recursive self-eating).

The Right Way

Use a separate private field:

private int age;

public int Age
{
    get { return age; }
    set { age = value; }
}

Or just use an auto-property:

public int Age { get; set; }

6. Inconsistent Naming

Being careful with case and names is super important in programming. C# is Case-Sensitive, so Name, name, NAME are three different identifiers.

Also, if you change a field or property name, make sure you change it everywhere! Rider can help refactor, but typos can still sneak in (especially if you have similar names).

7. Using the Wrong Modifier (static/instance)

Sometimes beginners mix up instance methods and static methods. The problem pops up when you try to access a field/method in a way that's not allowed by C# syntax.

Example

public class MathHelper
{
    public static int Add(int a, int b) => a + b;
    public int Multiply(int a, int b) => a * b;
}

var sum = MathHelper.Add(2, 3); // OK
var mul = MathHelper.Multiply(2, 3); // Error! 

The Multiply method isn't static, so you can't call it by class name without creating an object:

var helper = new MathHelper();
var mul = helper.Multiply(2, 3); // Now it's right

8. Mistakes When Inheriting Constructors

If your class inherits from another class, don't forget that the base class might require parameters in its constructor.

Example

public class Animal
{
    public string Name;

    public Animal(string name)
    {
        Name = name;
    }
}

public class Dog : Animal
{
    public Dog() { } // Error: base class requires name!
}

The compiler won't let you declare such a constructor. You need to explicitly call the base class constructor:

public class Dog : Animal
{
    public Dog(string name) : base(name) { }
}

9. Forgot to Implement All Interface Members

If your class implements an interface but doesn't implement all its methods — you'll get a compile error: "Class does not fully implement the interface".

Example

public interface IWalker
{
    void Walk();
    void Run();
}

public class Turtle : IWalker
{
    public void Walk()
    {
        Console.WriteLine("Slow and steady...");
    }
    // Oops! Forgot about Run!
}

The IDE will complain, and Turtle won't compile until you implement all interface methods.

10. Using Uninitialized Objects

In C#, objects are created explicitly with new. If you just declare a reference variable but don't assign it an object — it's null. If you try to access fields/methods, you'll get the famous NullReferenceException.

Example

Student student;
student.PrintName(); // Surprise!

You must initialize the object:

Student student = new Student("Alice");
student.PrintName();

11. Mistake: public Fields Instead of Properties

Old "anti-pattern": declaring all class fields as public. Why is this bad? Fields aren't protected, there's no control over changes, encapsulation is broken!

Example

public class Car
{
    public int speed; // Don't do this!
}

It's better to use properties:

public class Car
{
    public int Speed { get; set; }
}

Properties let you add checks, logic, restrictions:

private int speed;
public int Speed
{
    get { return speed; }
    set
    {
        if (value < 0) speed = 0;
        else speed = value;
    }
}

12. Implicitly Creating "Magic Numbers" or Strings

If you see 42, "Ivan", "SomeFile.txt" and other "magic" values right in method bodies — that's a potential mistake. It's better to use constants or fields.

Example

public class ConfigManager
{
    public void Save()
    {
        File.WriteAllText("config.txt", "some data"); // Magic string!
    }
}

Better:

public class ConfigManager
{
    private const string ConfigFileName = "config.txt";
    public void Save()
    {
        File.WriteAllText(ConfigFileName, "some data");
    }
}

13. Copy Mistake: Reference Variables Pointing to the Same Object

In C#, object variables are references. Assigning one variable to another just copies the reference, not the object itself. This often leads to "sudden" changes.

Example

Student s1 = new Student("John");
Student s2 = s1;
s1.Name = "Bob";
Console.WriteLine(s2.Name); // Will print "Bob"!

Why? Because s1 and s2 are two references to the same object!

14. No Feedback on Errors

It's bad when a class lets you assign invalid values. For example, a negative age.

Example

public class Human
{
    public int Age { get; set; }
}

var h = new Human();
h.Age = -50; // No problem...

The class logic should protect against nonsense values:

private int age;
public int Age
{
    get { return age; }
    set
    {
        if (value < 0)
            throw new ArgumentException("Age can't be negative.");
        age = value;
    }
}

15. Scope Confusion

Sometimes variables are declared with the same names in different scopes — inside a method and as class fields.

Example

public class MyClass
{
    int value = 10;

    public void Foo()
    {
        int value = 99;
        Console.WriteLine(value); // Will print 99, not 10!
    }
}

To clearly refer to the class field, use this.value.

16. Overriding Methods Without the override Keyword

When you want to override a virtual method from a base class, don't forget override!

Example

public class Animal
{
    public virtual void Speak() => Console.WriteLine("Animal speaks");
}

public class Cat : Animal
{
    public void Speak() => Console.WriteLine("Meow!"); // Not override!
}

Here, the base class method isn't overridden: the new method just hides the old one (shadowing), which can lead to surprises when working with base references.

The right way:

public override void Speak() => Console.WriteLine("Meow!");

17. Calling a Virtual Method from a Constructor

This isn't exactly a compile error, but it often leads to hard-to-find bugs. When a base class constructor calls a virtual method, and that method is overridden in a subclass — at the moment of the call, subclass fields might not be initialized yet.

Example

public class Animal
{
    public Animal()
    {
        Speak();
    }

    public virtual void Speak()
    {
        Console.WriteLine("Animal...");
    }
}

public class Cat : Animal
{
    public string Name { get; set; } = "Fluffy";

    public override void Speak()
    {
        Console.WriteLine($"Meow! I'm {Name}");
    }
}

Cat cat = new Cat();
// At the moment Speak() is called, Cat's constructor hasn't run yet, Name is still null!

18. Describing an Object Only Through the Constructor (No Properties)

If a class only has a constructor, and after creation the object can't be changed — that's fine for immutable objects, but not always convenient. In most cases, it's better to let the class user change properties (or at least some of them).

19. Ignoring Standard Naming Conventions

Class names start with a capital letter, methods too, fields — with a lowercase and underscore (or camelCase), constants — ALL CAPS. Using a single style not only makes code more readable, but also lowers the risk of random mistakes!

20. Unused Fields and Methods

If you created a field but never use it — that's "dead code". The IDE can highlight these cases. The fewer "dead zones", the easier it is to maintain your app!

2
Task
C# SELF, level 25, lesson 0
Locked
Fixing name collision error and using the `this` keyword
Fixing name collision error and using the `this` keyword
2
Task
C# SELF, level 25, lesson 0
Locked
Adding a default constructor
Adding a default constructor
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION