skip to Main Content

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 type DoStuff to type IDoStuff.

This doesn’t make sense. Was the linked post still correct after all?

If so, I have three questions.

  1. Why does the C# compiler not throw a build error if the cast was never going to succeed anyway?
  2. Why is casting to not implemented interfaces from classes with functions of the same name still not supported in C#? What’s the holdup?
  3. 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();
}

2

Answers


  1. In C#, you can cast from an interface to a concrete type but not the other way around. The type system can also cast between concrete types that implement the same interface.

    Login or Signup to reply.
  2. What you mean is called duck-typing and some languages like Go use that: If it walks like a duck, it must be a duck, right? C# does not support that, though. Instead, you need to explicitly implement the interface. The compiler is warning you about this by not allowing the implicit conversion. By using an explicit conversion, you are basically telling the compiler "Shut up, I know what I’m doing", and hence, the compiler shuts up and trusts you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search