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