Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interface inheritance and property hiding trouble

I recently introduced an interface on a base class for unit-testing purposes and ran into a weird problem. This is the minimal reproducible scenario:

interface IBase
{
    string Text { get; }
}

interface IChild : IBase
{
}

class Base : IBase
{
    public string Text { get { return "Base"; }}
}

class Child : Base, IChild
{
    public new string Text { get { return "Child"; }}
}

static void Main(string[] args)
{
    var child = new Child();
    Console.WriteLine(child.Text); // Outputs "Child"
    Console.WriteLine((child as Base).Text); // Outputs "Base"
    Console.WriteLine(((child as Base) as IBase).Text); // Outputs "Child"
}

The output of the first two Console.WriteLine commands is logical, but I fail to accept the output of the last one, it even outputs Child when using a temporary variable of type Base. Can anyone explain what is happening here?

UPDATE

By removing the interface IChild, ((child as Base) as IBase).Text suddenly results in "Base". Which makes me conclude that, as long as Child implements IBase (directly or through interface inheritance) the result will be "Child" instead of "Base".

This can get really tricky when you refactor a method in an other class to take an argument of IBase instead of Base, as it suddenly results in different behavior.

like image 722
huysentruitw Avatar asked Nov 13 '15 12:11

huysentruitw


People also ask

Do interfaces hide information?

Interfaces are not used to "hide" anything per se. It is used to establish a contract between the caller and the implementation. This contract promises that "these methods and properties will be here, and they will not change".

Does interface use inheritance?

Interfaces can inherit from one or more interfaces. The derived interface inherits the members from its base interfaces. A class that implements a derived interface must implement all members in the derived interface, including all members of the derived interface's base interfaces.

Are properties allowed in interface?

Interfaces, as defined by MSDN "contain only the signatures of methods, delegates or events." However, since propertiespropertiesA property, in some object-oriented programming languages, is a special sort of class member, intermediate in functionality between a field (or data member) and a method.https://en.wikipedia.org › wiki › Property_(programming)Property (programming) - Wikipedia are no more than syntactic sugar for a get and set method, they are also allowed in interfaces.

Which is better interface or inheritance?

Both Methods Work (Interfaces and Multiple Inheritance). Interfaces are better when you have several years of experience using Multiple Inheritance that have Super Classes with only method definition, and no code at all.


1 Answers

Basically you are casting here:

(child as Base) to Base and you're using Base's Text field. It's clear.

But in here:

(child as Base) as IBase you are casting Child to Base and then to IBase which means you are casting Child to IBase, which means Child's Text will be displayed. You are not changing the of underlying object by using as.

So (child as Base) as IBase here is the same as child as IBase.

EDIT:

Edited question does not change the fact that this answer is correct. As @InBetween said it is just changing the way how implementation of Text property is resolved. So Child class no longer implements IBase directly, so now Base's Text would be used as best match. Basically it is just using first class implementing IBase

like image 89
Kamil Budziewski Avatar answered Sep 19 '22 00:09

Kamil Budziewski