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.
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".
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With