Home Dashboard Directory Help
Search

Allow user-defined implicit type conversion to interface in C# by DanielKzu


Status: 

Closed
 as Won't Fix Help for as Won't Fix


86
2
Sign in
to vote
Type: Suggestion
ID: 318122
Opened: 12/16/2007 10:02:16 PM
Access Restriction: Public
0
Workaround(s)
view

Description

The documentation (http://msdn2.microsoft.com/en-us/library/aa664464(VS.71).aspx) is quite explicit:

"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."

This constraint doesn't seem very useful in many scenarios. For example, imagine you have an Adapter<T>, which may use remoting messages or any other interception mechanism to adapt to a given type (same case would apply to a Mock<T>). In both cases, the adapter (or mock) would internally contain an object that would implement the T, and perform the adaptation/mocking as necessary. Simply assigning the adapter/mock to a T should invoke the implicit conversion operator so that the user is not forced to access the inner interface through an explicit property.
Details
Sign in to post a comment.
Posted by eisenpony on 4/20/2012 at 9:05 AM
As mentioned by the OP "the adapter (or mock) would internally contain an object that would implement the T, and perform the adaptation/mocking as necessary"

This would make extensions of existing applications significantly easier.
Posted by Tim Kellogg on 3/14/2012 at 10:20 AM
I'd like to see operators be available in the same way as extension methods. This could be a possible solution to this problem, but it also solves other problems too
Posted by GuiSim on 11/10/2010 at 1:31 PM
Any update ? This seems like a valid suggestion and an update from Microsoft would be appreciated.
Posted by Jaystation on 9/7/2010 at 8:07 AM
So this was "Close as Won't Fix" for C# 4.0; can it be reopened for future consideration?

The explanation given was that it didn't make the cut for prioritization, so it seems that there is not a technical objection to future inclusion.
Posted by Evan H on 6/3/2010 at 12:35 PM
Any update on this suggestion?
Posted by Michael Sync on 11/4/2009 at 8:23 PM
I thought you guys will add this feature in C# 4.0. but ::((
Posted by DanielKzu on 2/20/2009 at 9:40 AM
I've hit a wall AGAIN with this issue. I wish there was a solution sooner than later...

See http://moq.uservoice.com/pages/general/suggestions/122731-simplify-custom-matchers
Posted by Microsoft on 4/24/2008 at 4:43 PM
Thanks again for your suggestion. After having done feature planning for the next release of C# I regret to say that this feature is not being added. We have to do some harsh prioritization, both because of our implementation and testing resources, but also because we need to keep the number of new langauge features at a manageable level - depending on how you count, we are adding only four language features to C# this time around. Unfortunately many great suggestions just can't make it in because of that.

I apologize that this is a "canned" follow-up answer, sent out as a result of our feature planning for the next release. In most cases I or someone else already replied individually to your suggestion - please let us know if you feel it hasn't been adequately addressed.

Thanks again for taking the time to share your ideas with us. Please keep them coming!

Mads Torgersen, C# Language PM.
Posted by DanielKzu on 2/4/2008 at 5:12 PM
Yup, agreed that with proper Equals/== overrides this could be handled, but it will certainly require very strict guidelines in order to avoid messy libraries WRT equality and casting.

And I see the point on the confusing situation with upcasting to object...

I guess this won't make it to vnext after all :). At first I thought it was much simpler...
Posted by DanielKzu on 2/4/2008 at 4:59 PM
I'd love to see this restriction go away for vNext. It's definitely something that will add flexibility that can be leveraged to improve usability of APIs making extensive use of adaptation/proxying.

Thanks for considering it!
Posted by David A Nelson on 2/4/2008 at 2:10 PM
I think the way to solve the problem you describe is to adhere to the .NET framework design guidelines. If a conceptual object can be represented by two distinct objects (the object itself and its "interface dummy"), then the equality operator on that type needs to be overloaded to account for whatever relationships are appropriate. Yes, its a pain in the butt, but it works.

I agree with kzu: as long as library designers follow the guidelines on when to implement an implicit conversion operator, I see no reason why that operator shouldn't be called when converting to or from an interface type.

Converting from an interface type to an interface type is a little more dicey; I'm not sure how I think that should be handled at this point.
Posted by Microsoft on 2/4/2008 at 11:47 AM
Thanks for the suggestion for Visual Studio 2008!

We are doing our feature planning now for the next version of the C# language and will soon be investigating all of our active language suggestions. If you have any further information about this suggestion, please add a comment.

Alex Turner
Program Manager
Visual C# Compiler
Posted by Pavel Minaev [MSFT] on 12/26/2007 at 11:25 PM
Mainly because with a downcast, you have the guarantee that, if the cast succeeds object identity remains the same. That is:

Foo obj;
...
obj == (IEnumerable)obj;
obj == (Foo)(IEnumerable)obj;
// etc

One could argue that the actual problem is the lack of distinction between conversion and casting in C#; or even further, the lack of separate casts for references, and for objects they reference. Technically, given a reference "obj" to some object, downcast of the reference to another class type, and conversion of the object itself to that same class type, are two distinct things; yet they are conflated in C# syntax due to the "implicitly dereferencing except when we're not" semantics of object references.
Posted by DanielKzu on 12/26/2007 at 12:38 PM
And why is it that you'd want to act differently if the interface is implemented by the object itself as opposed to an implicit conversion? I'm missing something obviously...

If you do

var e = obj as IEnumerable;

the implicit conversion should be called too, and if you end up with a non-null e, then why does it matter if it's the target obj itself or some adaptation built on the fly to expose that interface?
Posted by Pavel Minaev [MSFT] on 12/26/2007 at 4:31 AM
The problem is that for a reference to any object type, you can already try to cast it to any interface type (to see if the object supports that interface or not). One way to interpret it is to say that all classes have an explicit overloaded conversion operator for all existing interface types. When you introduce user-defined conversion operators to interfaces, you do in effect silently override that existing semantics. It's even worse with generics - let's say that I have something like this:

void Foo<T>(T obj)
{
// check to see if T supports interface IEnumerable... or not? What if T actually has operator IEnumerable()?
IEnumerable e = obj as IEnumerable;
if (e != null) { ... }
...
}

If this is changed, then: 1) some existing code may be broken, and 2) one would require to upcast everything to Object first before trying to cast to any interface type for the purpose of testing support for that interface, so as to avoid invoking a user-defined conversion operator instead.

Sounds like a bad idea to me.
Posted by Avery Lee on 12/17/2007 at 11:16 PM
I'm interested too in the reasoning behind this decision and think that the rationale is worth adding to the documentation. Given that C# doesn't allow for user-defined conversion operators between base and derived classes, my guess is that interfaces are prohibited here because it is impossible for the compiler to statically check for violations and would prohibit certain optimizations that assume interface casting transitivity (A->B, B->C implies A->C).
Sign in to post a workaround.