Overloading in generic interfaces

J

Jon Skeet [C# MVP]

Ben Voigt said:
It's not the calls that have unusual behavior, that's well defined. It's
the override behavior during implementation.

What exactly do you mean? I'm afraid I didn't fully follow either
sentence. Note that the C# 3.0 compiler warns that the behaviour
*isn't* specified.

Are you suggesting that the CLR is buggy but that the C# specification
*does* say which version should be called, or that the C# compiler is
definitely generating the right calls, but how those calls are resolved
is undefined?
 
C

Christof Nordiek

Jon Skeet said:
Leaving the spec itself aside, I'm not sure this isn't actually a CLR
issue. The IL generated for the calls themselves is the same whichever
way round the interface is declared:

callvirt instance void class IFoo`2<!!T,!!P>::Bar(!0, !1)
...
callvirt instance void class IFoo`2<!!T,!!P>::Bar(!1, !1)

But that is the call of the interface members. Each of them choses the right
interface member. The problem is, how the interface member is maped to the
methods.
The calling occurs on a constructed class, where the two overloads can
clearly ditinguished.
The interface mapping for NastyFooImpl occurs on a constructed type, where
the members can't be distinguished. We'de have to look how the interface
mapping is defined in the IL to see, if the C# compiler or the CLR makes the
decission.

Christof
 
C

Christof Nordiek

Jon Skeet said:
The C# 3.0 compiler can explain it for you, now I've tried it:

Test.cs(11,10): warning CS0473: Explicit interface implementation
'IFoo<...>.Bar' matches more than one interface member. Which
interface member is actually chosen is implementation-dependent.
Consider using a non-explicit implementation instead.

Still, from the specs, the implementation should map an both members. So
it's not implementation defined. Also, the distinction can't be made by
using non-explicit implementation.

But maybe, there is a change in the interface mapping rule between C#2.0 and
C#3.0

Christof
 
J

Jon Skeet [C# MVP]

But that is the call of the interface members. Each of them choses the right
interface member. The problem is, how the interface member is maped to the
methods.
Agreed.

The calling occurs on a constructed class, where the two overloads can
clearly ditinguished.
The interface mapping for NastyFooImpl occurs on a constructed type, where
the members can't be distinguished. We'de have to look how the interface
mapping is defined in the IL to see, if the C# compiler or the CLR makes the
decission.

I've made what I think is a fairly important discovery, in terms of
the difference that is made by reordering the interface members. One
way round, the IL for the explicit implementation is:
.override method instance void class IFoo`2<int32,int32>::Bar(!
1, !1)

The other way round, it's
.override method instance void class IFoo`2<int32,int32>::Bar(!
0, !1)

In other words it's explicitly implementing different methods, which
explains everything else, I think. That would put the ball in the C#
compiler's court (rather than the CLR's) but it doesn't answer whether
it's a C# compiler *bug* or a problem with the spec.

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top