• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

C# Inheritance: Virtual, Override, New, and Hidden Dangers

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.


C# inheritance is quite easy to implement but sometimes complex to understand.

Sure, most developers know what virtual, override, and new do. But what if we throw in a couple of casts and a few extra levels of inheritance? Now things aren’t so straightforward.

This article assumes you already know what inheritance is.

Initial Setup:


internal class Animal
{
public virtual void sound()
{
Console.WriteLine("Animal makes noise");
}

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

internal class Dog : Animal
{
public override void sound()
{
Console.WriteLine("Dog barks");
}

public virtual new void move()
{
Console.WriteLine("Dog runs");
}
}

internal class SuperDog : Dog
{
public override void sound()
{
Console.WriteLine("Super Dog howls");
}

public override void move()
{
Console.WriteLine("Super Dog sprints");
}
}

internal class Duck : Animal
{
public new void sound()
{
Console.WriteLine("Duck quacks");
}

public override void move()
{
Console.WriteLine("Duck Duck go!");
}
}

❓ Question 1: What is the output?


Animal al = new Animal();
al.sound();
al.move();

Animal d1 = new Dog();
d1.sound();
d1.move();

Animal d2 = new SuperDog();
d2.sound();
d2.move();

Dog sd = new SuperDog();
sd.sound();
sd.move();

Animal dk = new Duck();
dk.sound();
dk.move();

❓ Question 2: What does virtual new mean?

  • Does it still hide the base implementation?
  • Does it still declare the method for further override?

❓ Question 3: Guess the output!

Update the Dog class like this:


internal class Dog : Animal
{
public override void sound()
{
base.sound();
Console.WriteLine("Dog barks");
}

public virtual new void move()
{
base.move();
Console.WriteLine("Dog runs");
}
}

Now what do you think this will print?


Dog d3 = new Dog();
d3.sound();
d3.move();

Constructors and Virtual Methods

Constructors are meant to initialize the class state before it can be used.


public class Base
{
public Base()
{
Console.WriteLine("Base constructor");
Init();
}

public virtual void Init()
{
Console.WriteLine("Init Called: Base class");
// Base logic (maybe logging or setup)
}
}

public class Derived : Base
{
private List<string> _logMessages;
private string _message = "Initialization starts";

public Derived()
{
_logMessages = new List<string>();
}

public override void Init()
{
Console.WriteLine(_message);
_logMessages.Add("Init Called: Derived class");
}
}

❓ Question 4: Answer the following:

  1. Does the above code run properly?
  2. What does the output look like?
✅ Solutions:


Question 1:


Animal al = new Animal();
al.sound(); // Animal makes noise
al.move(); // Animal moved

Animal d1 = new Dog();
d1.sound(); // Dog barks
d1.move(); // Animal moved

Animal d2 = new SuperDog();
d2.sound(); // Super Dog howls
d2.move(); // Animal moved

Dog sd = new SuperDog();
sd.sound(); // Super Dog howls
sd.move(); // Super Dog sprints

Animal dk = new Duck();
dk.sound(); // Animal makes noise
dk.move(); // Duck Duck go!

Question 2:

virtual new declares a method that:

  • Hides the current base class implementation, and
  • Allows the method to be overridden in future derived classes.

So yes, it hides the base method for the current class and opens it for further overriding.

Question 3:

If a method exists in the base class and is accessible (not private), base.MethodName() will work inside the derived class—whether it's overridden or hidden using new.

Output:


Animal makes noise
Dog barks
Animal moved
Dog runs

Question 4:

Does the above code run normally?

Hell no!

Why?

Assume we create an object like this:


Derived dd = new Derived();

What really happens:

  1. CLR starts memory allocation for the object.
  2. Field _message is declared and initialized.
  3. Field _logMessages is declared, but not yet initialized.
  4. The base class constructor is invoked (derived constructor hasn't run yet).
  5. Inside the base constructor, Init() is called.
  6. Because it's virtual, it dispatches to Derived.Init().
  7. In Derived.Init(), _logMessages.Add(...) is called—but _logMessages is null!
  8. ? NullReferenceException

Output before crash:


Base constructor
Initialization starts
Unhandled Exception: System.NullReferenceException
? Final Thought:


While this scenario may not be common in enterprise apps, it can easily slip in unnoticed—especially when refactoring or extending base functionality. Most exceptions are just mistakes we didn't anticipate.

If you like this article please leave a comment, i am new to blogging but love programming, i am trying to expand my circle and would now to interact with others, Thanks

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу