8

Say, I have an interface

public interface ISomeControl
{
    Control MyControl { get; }
    ...
}

Is it possible to define something like this:

public static implicit operator Control(ISomeControl ctrl)
{
    return ctrl.MyControl;
}

Or rather why can't I do that in C#?

5
  • 1
    @leppie What am I missing? Why is this approach absolutely wrong? Commented Sep 21, 2012 at 15:43
  • For starters an interface cannot have any implementation so you have nowhere to define that operator Commented Sep 21, 2012 at 15:44
  • 1
    I have no idea why :) You will to summon @ericlippert for that answer :) Commented Sep 21, 2012 at 15:45
  • IIRC, the CLR will allow to make such code, just not C#. Commented Sep 21, 2012 at 15:51
  • possible duplicate of Why can't I use interface with explicit operator? Commented Apr 20, 2013 at 11:58

2 Answers 2

5

What if you had a subclass of Control, and that subclass implemented the ISomeControl interface.

class SomeControl : Control, ISomeControl {}

Now a cast would be ambiguous -- the built-in upcast, and your user-defined conversion. So you can't provide user-defined conversions for interfaces.

Sign up to request clarification or add additional context in comments.

9 Comments

I can understand that allowing conversions from an interface to a class type would be ambiguous, but I don't see the ambiguity if a class defines a conversion operator from an interface to itself. If there exists a conversion from BaseType to Foo, a class DerivedType may also define a conversion to Foo without creating ambiguity. If a class doesn't implement a particular interface but a subclass does, casting a base-type reference to that interface should use the user-defined conversion (regardless of whether the referenced object implements the interface)...
...while using a derived-class reference should use the conversion which is statically defined for the derived class. Even in the case of Foo<T> : ISomething<T> specifying a conversion to ISomething<Int32> I don't see interfaces as posing any "problem" that classes wouldn't.
@BenVoigt: How is that situation different from Derived<T> : Base<T> with conversion operator from Derived<T> to Base<string>? The conversion operator is applied when trying to store to a Base<string> something that the compiler can tell is a type Derived<T> for some T, but can't tell that it's a Derived<string>. The idea that a cast to an interface is reference-preserving may happen to be true if the thing being cast is a reference type because of the lack of any other way to perform the cast, but a cast of a value type to an interface type is not...
...reference-preserving, and the cast of an unconstrained generic to a reference type may or may not be reference-preserving. Actually, there are many situations with generics where a user-defined conversion operator may be invoked to cast an object to what happens to be its own type, without complaint. The rules of what things are, or are not, ambiguous are weird. I find it strange, for example, that if Foo defines a widening conversion to Bar, and Bar defines a widening conversion from Foo, neither conversion will work because of "ambiguity". Why not declare that "conversion from" wins?
@supercat: You talk about a "new type", but in order for conversions to exist in both types and each be aware of the other type, it's hard to say one type is newer than the other.
|
1

You cannot do that.

C# specification says:

6.4.1 Permitted user-defined conversions

C# permits only certain user-defined conversions to be declared. In particular, it is not possible to redefine an already existing implicit or explicit conversion. For a given source type S and target type T, if S or T are nullable types, let S0 and T0 refer to their underlying types, otherwise S0 and T0 are equal to S and T respectively. A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:

  • S0 and T0 are different types.

  • Either S0 or T0 is the class or struct type in which the operator declaration takes place.

  • Neither S0 nor T0 is an interface-type.

  • Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

One way you can do it is to have a static method.

public class Control
    {
        public static Control FromISomeControl(ISomeControl ctrl)
        {
            return ctrl.MyControl;
        }
    }

3 Comments

This doesn't address "why?". Besides, I think he's talking about the Microsoft-provided Control class, so you can't add to it.
I don't know if this is the Framework Control class. I thought it is only an example.
Control is the Microsoft-provided class

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.