views:

630

answers:

2

I have a generic class that I'm trying to implement implicit type casting for. While it mostly works, it won't work for interface casting. Upon further investigation, I found that there is a compiler error: "User-defined conversion from interface" that applies. While I understand that this should be enforced in some cases, what I'm trying to do does seem like a legitimate case.

Here's an example:

public class Foo<T> where T : IBar
{
    private readonly T instance;

    public Foo(T instance)
    {
        this.instance = instance;
    }
    public T Instance
    {
        get { return instance; }
    }
    public static implicit operator Foo<T>(T instance)
    {
        return new Foo<T>(instance);
    }
}

Code to use it:

var concreteReferenceToBar = new ConcreteBar();
IBar intefaceReferenceToBar = concreteReferenceToBar;
Foo<ConcreteBar> concreteFooFromConcreteBar = concreteReferenceToBar;
Foo<IBar> fooFromConcreteBar = concreteReferenceToBar;
Foo<IBar> fooFromInterfaceBar = intefaceReferenceToBar; // doesn't work

Does anyone know a workaround, or can anyone explain in a satisfactory way why I shuouldn't be able to cast interfaceReferenceToBar implicitly to Foo<IBar>, since in my case it is not being converted, but only contained within Foo?

EDIT: It looks like covariance might offer salvation. Let's hope the C# 4.0 specification allows for implicit casting of interface types using covariance.

A: 

I suspect you'll probably find some help looking at this question and the first few answers.

Read the info in the links, more specifically, this series of posts.

Matthew Scharley
This applies to implicit casting of generic collections. My specific problem is related to implementing the implicit operator to cast a type. In my case, I'm writing the code to do the casting.
Michael Meadows
+13  A: 

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

Adam Hughes
I understand that it's part of the specification, implicit casting of an interface should be invalid in some cases, but in all?
Michael Meadows
I agree with you, I don't know why they made it invalid for all cases. In this case you can determine at compile time that the cast is (should be) valid.
Adam Hughes
I *believe* that the restriction on implicit interface casting has to do with how COM interop is implemented. COM uses QueryInterface, which .NET handles automatically. Allowing implicit interface conversion would interfere.
Mark