abstract class 'does not implement interface member ...'

  • Thread starter Ben Voigt [C++ MVP]
  • Start date
J

Jon Skeet [C# MVP]

If the interface is public, all it's implemantations have to be public. But
if the interface is internal, the implementation of it's members remain
internal if they are implemented implicitly.

No they don't - they have to be declared public:

using System;

internal interface IFoo
{
void Bar();
}

class Test : IFoo
{
static void Main()
{
}

internal void Bar()
{
}
}

fails to compile with the error:
Test.cs(8,7): error CS0536: 'Test' does not implement interface member
'IFoo.Bar()'. 'Test.Bar()' is either static, not public, or
has the
wrong return type.

You *have* to make the method public in order to implement the
interface implicitly.

At least, that's as far as I can see - could you give an example of
what you mean?

Jon
 
C

Christof Nordiek

Christof Nordiek said:
If the interface is public, all it's implemantations have to be public.
But if the interface is internal, the implementation of it's members
remain internal if they are implemented implicitly.

Oops, I meant: the implementation of it's members remain internal if they
are implemented *explicitly*.

Christof
 
C

Christof Nordiek

Jon Skeet said:
At least, that's as far as I can see - could you give an example of
what you mean?

What I actually meant was 'explicitly' not 'implicitly'. I mixed them up
somehow.

Christof
 
J

Jon Skeet [C# MVP]

Oops, I meant: the implementation of it's members remain internal if they
are implemented *explicitly*.

In that they can't cast to the interface? Yes, that makes sense.

Jon
 
B

Ben Voigt [C++ MVP]

Christof Nordiek said:
Oops, I meant: the implementation of it's members remain internal if they
are implemented *explicitly*.

Not quite. They are only callable from internal code, true, but unlike a
proper internal member:

(1) They can't be invoked on the class object, you have to cast to interface
first.
(2) They can't be abstract or virtual. You can implement the interface
again in a derived class, but then I think you can't refer to the base
implementation any longer.
 
B

Ben Voigt [C++ MVP]

Christof Nordiek said:
The Method ProxiedOperation in InvocableInternals is not accepted as
implementation of ProxiedOperation of IInvocable, because it's neither
public nor an explicit interface implementation.
You could try following

public abstract class InvocableInternals: IInvocableInternals
{
string IInvocableInternals.ProxiedOperation{get {return
ProxiedOperation;}}

internal abstract string ProxiedOperation {get;}

......
}

I know you can, but adds extra layers of indirection at runtime, entirely
needlessly.
 
C

Christof Nordiek

Ben Voigt said:
Not quite. They are only callable from internal code, true, but unlike a
proper internal member:

(1) They can't be invoked on the class object, you have to cast to
interface first.

This cast wouls only be a typecheck at compiletime.
(2) They can't be abstract or virtual. You can implement the interface
again in a derived class, but then I think you can't refer to the base
implementation any longer.

You still can do all this. You can write internal members and then call this
from the implementations.

This surely is more code. That's why I said:

<quote>
But yes, an extention of the interface mapping rules, such that members of
an internal interface can map on internal members may be usefull.
</quote>

Christof
 
C

Christof Nordiek

Ben Voigt said:
I know you can, but adds extra layers of indirection at runtime, entirely
needlessly.

Maybe, but only, because the implementors of C#/.NET didn't consider it
worth to optimize this away. I don't see why this should work different in
runtime.

More problem I see with the extra code which makes the code a bit less
readable and maintainable.

Christof
 
B

Ben Voigt [C++ MVP]

Christof Nordiek said:
Maybe, but only, because the implementors of C#/.NET didn't consider it
worth to optimize this away. I don't see why this should work different in
runtime.

I don't see how it can avoid being different at runtime. In order for the
JIT to remove the function call, it would have to inline the code, and it
doesn't have enough information for that.
 
C

Christof Nordiek

Ben Voigt said:
I don't see how it can avoid being different at runtime. In order for the
JIT to remove the function call, it would have to inline the code, and it
doesn't have enough information for that.
Given that we compare explicit implementation of abstract class with calling
an abstract method in an explicit method:
In the first scenario the interface member has to be mapped to an method
wich itself is an entry in a v-table.
In the second scenario the runtime sees that the method is nothing more,
than a call of a virtual/abstract method and could transform this call in
absolute the same manner as in the first scenario.

Am I missing something?

Christof
 
B

Ben Voigt [C++ MVP]

Christof Nordiek said:
Given that we compare explicit implementation of abstract class with
calling an abstract method in an explicit method:
In the first scenario the interface member has to be mapped to an method
wich itself is an entry in a v-table.
In the second scenario the runtime sees that the method is nothing more,
than a call of a virtual/abstract method and could transform this call in
absolute the same manner as in the first scenario.

Am I missing something?

The abstract class explicit interface implementation will be called through
an interface, so it must be an entry in a v-table. The derived class
implementation is polymorphic (potentially many classes derived from the
abstract class), so it must be dispatched through the v-table as well.

If you could use "internal abstract ReturnType Method(arguments)" to
implement the interface, then the derived class method could be stored in
the interface v-table and invoked on the first dispatch. I don't see how
this is possible using the shim layer. You think that the JIT does reverse
inlining, where the interface v-table entry gets replaced by a derived
method that combines the base implementation with the (now known) inlined
derived instance? But that would break reflection, so I'm quite sure it
isn't being done.

public delegate void SimpleDelegate();

internal interface ISecret
{
void TellLocation();
}

public abstract class SecretBase : ISecret
{
abstract internal void TellLocation();
void ISecret.TellLocation() { TellLocation(); }
}

public class SecretHideout : SecretBase
{
internal void TellLocation() { ... }
}

public class SecretFortress : SecretBase
{
internal void TellLocation() { ... }
}

ISecret hideout = new SecretHideout();
ISecret fortress = new SecretFortress();

SimpleDelegate tell1 = hideout.TellLocation;
SimpleDelegate tell2 = fortress.TellLocation;

Assert.AreSame(tell1.Method, tell2.Method);


Now, can you suggest any way for the JIT to eliminate the second v-table
dispatch without breaking the assertion? With the alternate syntax, the
assertion would be expected to fail, but here there is only one
implementation of ISecret.TellLocation so it must succeed.
 
C

Christof Nordiek

Ben Voigt said:
public delegate void SimpleDelegate();

internal interface ISecret
{
void TellLocation();
}

public abstract class SecretBase : ISecret
{
abstract internal void TellLocation();
void ISecret.TellLocation() { TellLocation(); }
}

public class SecretHideout : SecretBase
{
internal void TellLocation() { ... }
}

public class SecretFortress : SecretBase
{
internal void TellLocation() { ... }
}

ISecret hideout = new SecretHideout();
ISecret fortress = new SecretFortress();

SimpleDelegate tell1 = hideout.TellLocation;
SimpleDelegate tell2 = fortress.TellLocation;

Assert.AreSame(tell1.Method, tell2.Method);


Now, can you suggest any way for the JIT to eliminate the second v-table
dispatch without breaking the assertion? With the alternate syntax, the
assertion would be expected to fail, but here there is only one
implementation of ISecret.TellLocation so it must succeed.

When generating the v-table entry for ISecret in class SecretHideout it
detects, that the implementation simply delegates the call to another
method. Then it lets the v-table entry point directly to that method.

If that really gives a performance boost in many cases, I'm sure they would
implement such optimization.

BTW: Do you have any evidence, that this isn't implemented in that way and
that this rises performance issues? Until now our discussion is only
theorie.

Christof
 
B

Ben Voigt [C++ MVP]

Christof Nordiek said:
When generating the v-table entry for ISecret in class SecretHideout it
detects, that the implementation simply delegates the call to another
method. Then it lets the v-table entry point directly to that method.

If that really gives a performance boost in many cases, I'm sure they
would implement such optimization.

BTW: Do you have any evidence, that this isn't implemented in that way and
that this rises performance issues? Until now our discussion is only
theorie.

Only that the optimization you describe is illegal because it would break
the example code I gave. Note that possibly Assert.AreSame is the wrong
test, really whether the MethodToken is the same is what matters.
 

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