Проверка наследованного класса в иерархии

Я плохо знаю термины и концепции ООП, по-этому могу что-то перепутать. По-этому, перейду сразу к примеру.
Есть классы:

        private class Base { }
        private class A : Base { }
        private class B : A { }
        static void Main(string[] args)
        {
            Base b = new B();
            Console.WriteLine(b is A); //true
            Console.WriteLine(b is B); //true

            B bb = new B();
            Console.WriteLine(bb is A); //true
            Console.WriteLine(bb is B); //true

            Console.ReadLine();
        }

Мне надо проверить, является ли переменная экземпляром класса B. А он выдаёт true даже при сравнении b с A. И так, видимо, будет для всей иерархии :thinking: То есть, если сравниваемые классы принадлежат одной иерархии, то всегда будет выдано true.
А как тогда быть? :thinking: Использовать .GetType().Name?

Да, точно. Вот так работает:
b.GetType() == typeof(B)
Очень странно. Никогда с этим не сталкивался. Я думал, что is делает то же самое :thinking: Но тогда не совсем понятно, зачем вообще нужен is :man_shrugging:

Дык как раз и нужен для того, что показано в первом посте, проверить является ли что-то чем-то. Обычно же важен не “конечный” класс, а нужно просто узнать можно ли с этим что-то делать, например, если в графическом редакторе objectOnCanvas is Text, то можно поменять шрифт, а если is Shape, то только цвет, при этом Shape может быть Ellipse, Rectangle и т.д.

А как мы удостоверимся, что классы Text и Shape не принадлежат одной иерархии (то есть, один не наследован от другого)? :thinking: Ну мало ли и такое возможно :man_shrugging:

То есть? :thinking:

А, ну :thinking: Если так рассуждать, то наверное да :man_shrugging: Но я всё-равно не очень улавливаю логику. Это больше похоже на интерфейс тогда :thinking:
Я просто думал, что is это точная проверка на соответствие (как .GetType()).