Internal interfaces & .NET - Implicit vs. Explicit implementation

Internal interfaces & .NET - Implicit vs. Explicit implementation

Old forum URL: forums.lhotka.net/forums/t/1324.aspx


skagen00 posted on Monday, September 25, 2006

This is really more of a .NET question - I'm working to implement an internal interface among different concrete types of a base class for a polymorphic collection.

Why isn't this valid?

internal interface IMyInterface

{ void Test(); }

public class MyClass : IMyInterface

{

internal void Test() {...}

}

It finds a couple options OK:

public void Test() {...} <-- I don't want this, because I don't want it to be public!

void IMyInterface.Test() {...} <-- I'd rather not do this for code gen reasons. 

The former is gotten without explicit implementation and the latter with explicit implementation.

Why isn't the very first one valid? I just don't get it.

DansDreams replied on Monday, September 25, 2006

The short answer is that interfaces members must be public by Microsoft's definition.

You can "hide" the interface itself from outsiders with accessibility modifiers, but you're expected to trust yourself when using it internally.  :)

skagen00 replied on Monday, September 25, 2006

If you actually explicitly implement the interface it does keep the members as internal. I did a really quick test to make sure of this.

So it seems like for the purposes of implicit implementation, you can't do it and make it internal - you have to explicitly implement the interface in order for it to be truly internal.

Just seems a little backasswards to me. If I declare my interface is internal my implementations should be internal, end of story.

Oh well! Thanks for your response.

 

DansDreams replied on Monday, September 25, 2006

I can see your point of view, but on the other hand the very purpose of an interface is to declare in a very public way that I support such-and-such functionality.

Explicit implementations come with their own quirks, and I would expect

void IMyInterface.Test()

to really be creating an public method in the implementing class and that

internal void IMyInterface.Test()

wouldn't compile.  Did you check trying to access MyClass from outside the assembly in your second case to verify it really was internal?

skagen00 replied on Monday, September 25, 2006

It actually is hidden - yeah, I tested it from a separate project - the explicit implementation is indeed internal and the implicit implementation (publicly declared) is obviously public.

The only reason why I was going to utilize this is for purposes of the Update method of a polymorphic collection - it needs to Update(), DeleteSelf() and Insert() on interface members and I don't want those three methods public - so I figured I'd utilize an internal interface.

Just doesn't seem like there's a really elegant way to handle the problem.  

DansDreams replied on Monday, September 25, 2006

Oh yeah, I see where you're going.  That's one of the primary reasons Rocky went the reflection route on the DataPortal_XYZ methods as I recall.

But the explicit implementation working that way is news to me and a little surprising.  Since interface methods are public by definition, and the default accessibility for a method is private unless otherwise specified, I don't understand how we got to internal.  It's like the method has the accessibility of the interface itself if it's explicitly implemented.

But the stated purpose of an explicit implementation is essentially to "hide" the implementation, so maybe that makes sense - and serves your purposes.  In other words, Microsoft's position is

  1. interface members are public by definition
  2. explicitly implement the interface if you want to hide them

DansDreams replied on Monday, September 25, 2006

Yeah, I think that would be the recommended solution the more I think about it.  Since the interface itself is not public, you wouldn't be able to cast the object to it from outside the assembly, and without doing that you couldn't see those methods that were explicitly implemented.  Exactly what you want, but perhaps a little more convoluted than you'd like.  But I think it all makes sense taken as a whole.

And, if that's the case, why couldn't this be used for the DataPortal_XYZ methods Rocky?

Brian Criswell replied on Monday, September 25, 2006

Would that not be because a CSLA interface would need to be publicly visible to be implemented by your business objects?  This kind of solution would need to be implemented within a business object assembly.

skagen00 replied on Monday, September 25, 2006

Ignore this post, its in flux.

ajj3085 replied on Monday, September 25, 2006

Reflection I would think is much slower than casting.

skagen00 replied on Monday, September 25, 2006

You're definitely correct on that one, Andy.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp02172004.asp

Another post, probably a more practical one, is here:

http://west-wind.com/weblog/posts/351.aspx

Of course, on a Web app like mine, this is not going to be the bottleneck. I am probably going to utilize reflection for a "cleaner" solution for now and then come back to it later. I have a few code gen issues otherwise that I don't want to deal with right now.

 

ajj3085 replied on Tuesday, September 26, 2006

Yes, reflection is slower, but there are better things to optimize first.  Data access and for a web app, getting pages from server to client are the biggest bottlenecks.

ajj3085 replied on Monday, September 25, 2006

DansDreams:
And, if that's the case, why couldn't this be used for the DataPortal_XYZ methods Rocky?


I think so that you can create your own DP's without forcing them into the Csla assembly.

ajj3085 replied on Monday, September 25, 2006

Dan,

The reason the explicit implementation works as it does is because you cannot see explicitly defined members unless you cast to the interface... and if the interface is not public, you can never cast to said interface.

Its not that explicitly implemented interfaces are 'hidden' per say; it just means to 'see' the implemntation, you must cast explicitly to the interface.  Try this:

public interface IPerson {
    string Name { get; }
}

public class Person : IPerson {
    string IPerson.Name { get "My Name"; }
}

public static void Main() {
   Person p;
   IPerson iP;

   p = new Person();
   //Console.WriteLine( p.Name ); // This wont' compile if uncommented

    iP = (IPerson)p;
    Console.WriteLine( iP.Name );
}


Copyright (c) Marimer LLC