Jeroen
Jeroen

Reputation: 989

Implicit operator to an interface through an adapter in C#

I have a class that doesn't implement an interface, but it needs to. I can't change the class itself, so I wanted to create an implicit operator from ClassA to IInterface. This can't be done by design (I get the message: "User-defined conversion to interface"). So I want to create an adapter for it like so:

    public interface IInterface
    {
        void Method();
    }

    public class ClassA
    {
        public void Implementation()
        {
        }
    }

    public class ClassAToIInterfaceAdapter : IInterface
    {
        public ClassAToIInterfaceAdapter(ClassA classA)
        {
            ClassA = classA;
        }

        public void Method()
        {
            ClassA.Implementation();
        }

        private ClassA ClassA { get; set; }

        public static implicit operator ClassAToIInterfaceAdapter(ClassA classA)
        {
            return new ClassAToIInterfaceAdapter(classA);
        }
    }

    public void Test2()
    {
        var classA = new ClassA();
        IInterface i = classA;
    }

Here I get the compiler error:

error CS0266: Cannot implicitly convert type 'ClassA' to 'IInterface'. An explicit conversion exists (are you missing a cast?)

Adding an explicit cast will fix the compiler error, but not the runtime error:

Unable to cast object of type 'ClassA' to type 'IInterface'

Two questions about this:

  1. Why does this error occur? There is a cast possible from ClassA to IInterface.
  2. Can this be done at all without explicitly using the adapter in the code?

Upvotes: 0

Views: 645

Answers (1)

Maarten
Maarten

Reputation: 22955

The reason the error occurs is that, yes there is a cast possible, but you are not indicating anywhere (in your method Test2) that the conversion should be done using the ClassAToInterfaceAdapter class. You could have a dozen implicit operators defined in as many classes, but that is no reason to use them.

You have to indicate the type, and if the type has an implicit operator, than it will be used. This works because the type ClassAToInterfaceAdapter contains the implicit operator:

public void Test2() {
    var classA = new ClassA();
    ClassAToInterfaceAdapter i = classA;
}

Edit:

From another SO answer

The reason you can't do this is because it is specifically forbidden in the C# language specification:

A class or struct is permitted to declare a conversion from a source type S to a target type T provided all of the following are true:

  • ...
  • Neither S nor T is object or an interface-type.

and

User-defined conversions are not allowed to convert from or to interface-types. In particular, this restriction ensures that no user-defined transformations occur when converting to an interface-type, and that a conversion to an interface-type succeeds only if the object being converted actually implements the specified interface-type.

Source

Upvotes: 1

Related Questions