I have a class and an interface as follows:
internal class DoStuff
{
public int X { get; }
public void Do() => WriteLine(X);
public DoStuff(int X) => this.X = X;
}
internal interface IDoStuff
{
void Do();
}
The class DoStuff
does not implement the interface IDoStuff
. Therefore, there does not exist an implicit conversion. However, Visual Studio's Intellisense said that an "explicit conversion did exist". This made sense to me, since if an interface had all the same methods of a class, there shouldn't be a reason why you couldn't cast from the class to the interface. I logically inferred that the only reason you could specifically implement an interface in type declaration was for explicit implementation.
I read this post, which claimed it was not possible. However, it was written in 2011, and so I assumed that C# had changed since then. C# 5.0 was released in 2012, a year later, and I was on C# 11.0. So, to test my theory, I attempted to create and run the following C# (.NET 6 top-level code):
// Program.cs:
using static System.Console;
DoStuff d = new(2);
IDoStuff i = (IDoStuff)d;
i.Do();
return;
The code compiled fine, but when I tried to run it, it threw an InvalidCastException
on the 3rd line:
System.InvalidCastException
: Unable to cast object of typeDoStuff
to typeIDoStuff
.
This doesn't make sense. Was the linked post still correct after all?
If so, I have three questions.
- Why does the C# compiler not throw a build error if the cast was never going to succeed anyway?
- Why is casting to not implemented interfaces from classes with functions of the same name still not supported in C#? What's the holdup?
- I vaguely remember reading somewhere that it is possible to explicitly cast between different classes with identical elements. Is this true? If so, what is the difference?
If not, why then is the cast not working?
Here is the full combined code:
https://dotnetfiddle.net/WfAHC4
using static System.Console;
DoStuff @do = new(2);
IDoStuff iDo = (IDoStuff)@do;
WriteLine("a");
iDo.Do();
WriteLine("b");
ReadKey(true);
internal class DoStuff
{
public int X { get; }
public void Do() => WriteLine(X);
public DoStuff(int X) => this.X = X;
}
internal interface IDoStuff
{
void Do();
}