when compiling:
public interface IInvocable
{
object Operation { get; }
}
internal interface IInvocableInternals : IInvocable
{
bool OperationValidate(string args);
string ProxiedOperation { get; }
}
public abstract class InvocableInternals : IInvocableInternals
{
public object Operation { get { return ProxiedOperation; } }
}
But, I already knew the class didn't implement those functions. That's why
it is *abstract*. Please note that I've replaced all complicated types with
object or string to make a minimal reproduction. I don't want my internal
functions exposed publicly, I can't hide InvocableInternals because public
classes inherit from it, and I don't want to use a forwarder because, I'm
convinced that the JIT wouldn't be able to inline it.
Why isn't it allowed to just implement
"IInvocableInternals.OperationValidate" in the most derived class?
According to the language specification:
20.4.5 Abstract classes and interfaces
1. Like a non-abstract class, an abstract class must provide implementations
of all members of the interfaces that are listed in the base class list of
the class.
Or are you asking why the language specification is this way?
--
- Nicholas Paldino [.NET/C# MVP]
- m...@spam.guard.caspershouse.com
"Ben Voigt [C++ MVP]" <r...@nospam.nospam> wrote in message
news:%236aN$VDrHH...@TK2MSFTNGP06.phx.gbl...
Ok, but since the interface is internal, I should be allowed to:
public interface IInvocable
{
object Operation { get; }
}
internal interface IInvocableInternals : IInvocable
{
bool OperationValidate(string args);
string ProxiedOperation { get; }
}
public abstract class InvocableInternals : IInvocableInternals
{
internal abstract string ProxiedOperation { get; }
I see what you are getting at now. This is one of the things that has
always frustrated me as well. Honestly, I never saw any pitfalls to
allowing this, since abstract methods are the same as virtual methods
anyways when seen from the derived class on.
--
- Nicholas Paldino [.NET/C# MVP]
- m...@spam.guard.caspershouse.com
"Ben Voigt [C++ MVP]" <r...@nospam.nospam> wrote in message
news:Oc4kUgDr...@TK2MSFTNGP06.phx.gbl...
I've never understood this whole requirement about "type less visible than
...". Why can't I return an internal interface from a protected member
function, or vice versa? There are some perfectly valid combinations that
just can't be used currently. At most, the compiler should generate a
warning, definitely not an error.
Well, that's a different story. The issue with me is that abstract
members can not implement interface members.
However, saying that a protected member can not expose an internal
member is justified, because with a protected member, the possibility exists
that the protected member will be accessed outside of the assembly, which
would violate the internal member's visibility.
--
- Nicholas Paldino [.NET/C# MVP]
- m...@spam.guard.caspershouse.com
"Ben Voigt [C++ MVP]" <r...@nospam.nospam> wrote in message
news:entjJlEr...@TK2MSFTNGP05.phx.gbl...
> Ok, but since the interface is internal, I should be allowed to:
>
> public interface IInvocable
> {
> object Operation { get; }
> }
>
> internal interface IInvocableInternals : IInvocable
> {
> bool OperationValidate(string args);
>
> string ProxiedOperation { get; }
> }
>
> public abstract class InvocableInternals : IInvocableInternals
> {
> internal abstract string ProxiedOperation { get; }
> public object Operation { get { return ProxiedOperation; } }
> }
I'm not entirely clear about what you're asking about.
When I tried to compile the code you posted above, I got two errors, both
expected (at least to me):
OperationValidate was undefined, and
ProxiedOperation was not public
Since you provided no definition for OperationValidate, the error is not
surprising. This error is easily addressed by including an abstract
definition for the method in InvocableInternals. I don't see any problem
at all doing that.
Since interface members are required to be public, the second error is not
surprising either. This error is easily addressed by changing the
protection for ProxiedOperation so that it's public. The interface itself
is internal, so if you are concerned that InvocableInternals is public and
you don't want external code getting at the interface method
ProxiedOperation, I would think that an explicit interface declaration
would work around that issue, allowing the method to be public but
providing no means for external code to access it.
I've read Nicholas's reply to your posts, but I'm still not really clear
on what issue it is exactly you're having. If the above doesn't address
your concern, perhaps you can try to rephrase the question.
Pete
Hi,
I think the errors are reasonable and expected. I can't see any
problem with the errors. Why are they not expected?
Moty
> I think the errors are reasonable and expected. I can't see any
> problem with the errors. Why are they not expected?
That's my question exactly. :)
Protected members are visible from methods outside the assembly. They
therefore couldn't understand what such a member meant if any of the
parameter types or the return type. I think it's reasonable to prevent
members from being visible if they couldn't actually be understood.
> There are some perfectly valid combinations that
> just can't be used currently. At most, the compiler should generate a
> warning, definitely not an error.
No, I'm with the compiler on this front. However, it's a shame that
there isn't the *more* restrictive equivalent of "protected internal" -
i.e. "only visible to types which derive from this one *and* are in the
same assembly" - at which point it would be okay to return your
internal type.
However, that wouldn't solve your problem here - because interface
members are themselves implicitly public, so all the implementations
have to be public. It's very odd that the interface being internal
doesn't make all its members internal too.
--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
I'm often finding myself wanting an access level which is "members of the
enclosing type", but nothing like this is currently implemented.
True, I hadn't done anything about OperationValidate.
But, the provided definition of ProxiedOperation, in my opinion, should be
accepted by the compiler. Why are only public (implicit interface
implementation) and private (explicit implementation) allowed? In this case
internal visibility is desired, and C# provides no way to get it without an
additional runtime cost.
What I also don't like, is that while interfaces can have any visibility,
abstract base classes must have at least the same visibility as the deriving
class. This is inconsistent and makes no sense (to me).
Do you mean "enclosing" in terms of nested classes? If so, private is
fine:
using System;
class Test
{
static string privateMember;
static void Main()
{
privateMember = "Private";
new Nested();
}
class Nested
{
internal Nested()
{
Console.WriteLine(privateMember);
}
}
}
If you actually mean base types, then it doesn't help you of course.
I mean in terms of nested classes, and I mean on a per-member of nested
class basis. e.g. the nested class itself is publicly visible, ala
list::iterator, but carries data only meaningful to the enclosing class.
You've used internal, but that really isn't a very close fit. Especially
because .NET seems to force everything even somewhat interrelated to be
thrown into a single assembly.
<snip>
> But, the provided definition of ProxiedOperation, in my opinion, should be
> accepted by the compiler. Why are only public (implicit interface
> implementation) and private (explicit implementation) allowed? In this case
> internal visibility is desired, and C# provides no way to get it without an
> additional runtime cost.
One thing to note: explicit implementation isn't really private. It
doesn't fit in well with the normal public/internal/protected/private
etc taxonomy. It means "publicly available through an expression of the
interface type" - so it's effectively public if the interface is
public, because anyone could cast to the interface and then call the
method.
> What I also don't like, is that while interfaces can have any visibility,
> abstract base classes must have at least the same visibility as the deriving
> class. This is inconsistent and makes no sense (to me).
It makes sense to me - if you derive a public type from an internal
type, how would I know (from a different assembly) what members you've
inherited? It's the same argument as the parameter/return type one,
basically - you shouldn't be able to see things which refer to things
you can't see.
I've used an internal constructor (so that the enclosing class can see
it), but the class itself is implicitly private.
> True, I hadn't done anything about OperationValidate.
Since your original specifically asked about that compiler error, I hope
you can see where at least some of my confusion originated. :)
> But, the provided definition of ProxiedOperation, in my opinion, should
> be
> accepted by the compiler. Why are only public (implicit interface
> implementation) and private (explicit implementation) allowed? In this
> case
> internal visibility is desired, and C# provides no way to get it without
> an
> additional runtime cost.
Can you elaborate on why having an explicit-but-internal interface doesn't
accomplish what you want? It seems to me that that _does_ give you
internal visibility, without any additional runtime cost.
I admit that it seems a little odd that the implementation of an interface
is required to be less protected than the interface itself. However, I
see that as simply one of the many simplifications that C# has chosen,
favoring consistent easily-defined behavior over flexibility.
It's not an unreasonable requirement that interfaces simply require all
implementations to be public, given that the interface itself can be
restricted and explicitly implemented. Doing so ensures that all
protection is decided at the interface level, rather than the
implementation level, which seems to me to be a good design for an
interface.
> What I also don't like, is that while interfaces can have any visibility,
> abstract base classes must have at least the same visibility as the
> deriving
> class. This is inconsistent and makes no sense (to me).
I suppose that's in the eye of the beholder. It makes a lot of sense to
me, because it seems odd to me that you might have a class that derives
from some class, but which does not expose that class's functionality. If
you want to incorporate functionality of a more-protected class in a given
class, then simply hide the more-protected class as a member, rather than
deriving from it.
At the very least, it seems to me that this rule doesn't restrict what you
can do. It just changes how you have to do it.
Pete
> I admit that it seems a little odd that the implementation of an
> interface is required to be less protected than the interface itself.
And of course, I meant "equally or less protected" here
"internal" just isn't the same as "enclosing class", it doesn't enforce
encapsulation anywhere near as well, in fact it breaks it because
Intellisense will show those "internal" members to all coders working on the
same assembly.
A private interface declared in the enclosing class works, with explicit
implementation, but then you have to qualify every call with the interface
name... still not very nice.
How about "you don't, you see only members in my most derived types and in
public interfaces".
> basically - you shouldn't be able to see things which refer to things
> you can't see.
That principle totally eliminates inheritance as a means of reusing
implementation details. But I guess that's what the .NET architects wanted,
because they didn't provide non-public inheritance.
No, it doesn't. You can't override such a method, which you could with a
real internal method. Then you need *another* virtual method, declared with
the correct visibility, with a private explicit implementation forwarder.
That requires an extra v-table slot, and an extra function call at runtime,
because it is called polymorphically, thus preventing the JIT from inlining.
Try using that class from outside the enclosing class and you won't be
able to - because the nested class itself isn't visible outside the
enclosing class.
> A private interface declared in the enclosing class works, with explicit
> implementation, but then you have to qualify every call with the interface
> name... still not very nice.
True.
> > basically - you shouldn't be able to see things which refer to things
> > you can't see.
>
> That principle totally eliminates inheritance as a means of reusing
> implementation details. But I guess that's what the .NET architects wanted,
> because they didn't provide non-public inheritance.
I think you must be meaning something beyond the obvious, because the
idea that .NET stops you reusing implementation details via inheritance
is crazy in itself. Do you think that every class in the framework
reimplements all of its public members, rather than ever relying on the
base class's implementation? Do you do that when coding in .NET? Do you
always override *all* the virtual methods in *every* class? If not, you
*are* reusing implementation details via inheritance.
So, given that that can't be what you mean, what *do* you mean?
I mean that when you use inheritance, it's not an implementation detail.
It's a part of the public interface.
Guess you missed this in my earlier post: "the nested class itself is
>> Can you elaborate on why having an explicit-but-internal interface
>> doesn't accomplish what you want? It seems to me that that _does_ give
>> you internal visibility, without any additional runtime cost.
>
> No, it doesn't. You can't override such a method, which you could with
> a real internal method.
You seem to have shifted tracks here. I thought we were talking about the
question of restricting access to an interface implementation. When did
the question of whether the method can be overridden or not come up, and
in what way does the protection level of the method play a part?
Pete
Only the entire thread, the title of which begins with "abstract class",
thereby strongly suggesting overrides. And starting out with the statement
that the implementation would be provided in a more derived class.
But in any case, I elaborated on why that method didn't work, as you
requested. Trust me, I'd already considered that before posting in the
first place.
In any case, once again, the question is:
How do you define an interface on an public abstract class, giving the
members less than public visibility, the implementation of which is provided
in the more derived class? Bonus for not requiring extra runtime
indirection, a call through the interface v-table should be enough.
TTYL.
> Only the entire thread, the title of which begins with "abstract class",
> thereby strongly suggesting overrides. And starting out with the
> statement that the implementation would be provided in a more derived
> class.
Sorry...I didn't realize that was still a question. Since you _can_
declare an interface method as "abstract", I'm not really clear on what
the problem is yet. Is it your assertion that even though you can declare
the interface method as abstract, you are not permitted to override it in
a derived class?
The only issue I ran into trying to do what it _appeared_ to me you were
trying to do was the protection level of the abstract method. Because the
interface requires everything to be public, you can't make the method
internal (or anything else for that matter). But you certainly can make
it abstract.
(But it turns out, you can't make it abstract and explicit at the same
time...my lightbulb finally goes on...see below)
> [...]
> In any case, once again, the question is:
>
> How do you define an interface on an public abstract class, giving the
> members less than public visibility, the implementation of which is
> provided in the more derived class? Bonus for not requiring extra
> runtime indirection, a call through the interface v-table should be
> enough.
I think I finally see what your objection is. My apologies if I should
have seen this earlier, but I have to say your initial post was not at all
clear about what you were asking about, at least not to me (see my
previous comments about the compiler error you quoted versus what you're
actually asking about).
Anyway, I see that I get the CS0106 error when I try to combine abstract
and explicit interface implementation. The help topic for this error
reads, in part: "The abstract keyword is not allowed on an explicit
interface declaration because an explicit interface implementation can
never be overridden."
For what it's worth, I made the assumption that you could combine abstract
and an explicit interface declaration to do what you want. You even
seemed to reinforce this idea when you wrote "Why are only public
(implicit interface
implementation) and private (explicit implementation) allowed?" I haven't
found a way to use an explicit implementation at all, except when the
implementation is actually defined in the class declaring it (that is,
it's not virtual or abstract). Your statement seems to me to say that it
_is_ allowed, which is what got me confused.
Not that that really matters...more a point of reference in case you're at
all curious why it is I didn't get what you were trying to say.
So, to sum up:
* You can override an implicit interface definition, including an
abstract one
* You cannot override an explicit interface definition, and
* You cannot make an interface implementation anything except public
(whether that implementation is abstract or concrete, implicit or
explicit, green or yellow, whatever)
I'll ignore the first one, since that's something you _can_ do. :)
I don't fully understand the second one, and the third one would only make
sense to me if you had the option of overriding explicit interface
definitions. Since you can't, I would agree that it would be useful to be
able to at least modify the access of an implemented method of an
interface to match the protection level of the interface itself.
I can see why if the interface were public, for example, the
implementation would have to be public, but I'm at a loss to explain why
when the interface is internal, the implementation still needs to be
public.
In other words, at this point I think I finally see what you're
complaining about, and I don't have an answer. Maybe someone else does
(I'm actually a bit surprised that no one else has jumped in yet with a
good explanation of what's going on here).
Pete
If it only carries data meaningful to the enclosing class then why
have you made it public?
Jon
Right - yes indeed. I hope you can see why I was confused!
Maybe it's just because I haven't done much C++, but it feels to me
like that's only natural. Is making it an implementation detail a
common concept outside C++?
I tend to prefer composition over inheritance anyway, which may be why
I've never felt it to be a problem.
Jon
>> Guess you missed this in my earlier post: "the nested class
>> itself is publicly visible, ala list::iterator, but carries data only
>> meaningful to the enclosing class."
>
> If it only carries data meaningful to the enclosing class then why
> have you made it public?
I think he means _some_ of the data it carries is meaningful only to the
enclosing class. Presumably the class itself is public for a good reason.
I got the impression he went to bed (which is where I should be going
too), so you'll have to wait until tomorrow to find out if I'm right. :)
Pete
> On Jun 12, 7:43 am, "Ben Voigt [C++ MVP]"
>> I mean that when you use inheritance, it's not an
>> implementation detail. It's a part of the public interface.
>
> Right - yes indeed. I hope you can see why I was confused!
>
> Maybe it's just because I haven't done much C++, but it feels to me
> like that's only natural. Is making it an implementation detail a
> common concept outside C++?
At the risk of taking this thread away from the topic that Ben actually
wanted to talk about...
I'm unclear on the statement that "when you use inheritance, it's not an
implementation detail. It's a part of the public interface".
The way I read that, it's saying that in C#, inheritance is specifically
about defining the public methods a class exposes.
But I have to say, that's not the extent to which I use inheritance at
all, even in C#. You can inherit protected members, just as you can in
C++, and they provide the same benefit: an _implementation_ that is
reusable by the derived class. For that matter, private members may be
part of the inherited implementation as well.
So I'm confused about why inheritance is _not_ an implementation detail.
Since you both seem to agree on the point, maybe one of you can explain
what you're talking about to me. :)
Thanks,
Pete
In that case, one obvious way round it is to keep the class private,
but implement a public interface exposing the members he wants to be
public. That keeps creation etc tightly within the confines of the
enclosing class, while keeping public things public.
> I got the impression he went to bed (which is where I should be going
> too), so you'll have to wait until tomorrow to find out if I'm right. :)
True.
Jon
But you also end up with a runtime dynamic cast every time the client passes
said object back to you.
Implementation details can be changed without any changes by the client.
Inheritance clearly breaks through encapsulation. You can't inherit from an
internal or otherwise visibility-restricted class, and therefore the client
can always use your class in ways that changes to inheritance would break.
That's true - I hadn't considered the case where the object is passed
bi-directionally.
Jon
> Implementation details can be changed without any changes by the client.
> Inheritance clearly breaks through encapsulation. You can't inherit
> from an
> internal or otherwise visibility-restricted class, and therefore the
> client
> can always use your class in ways that changes to inheritance would
> break.
Ahh...I see what you mean. I agree that's true. And in fact, I'll go one
further and point out that you can't even hide a public class as you
inherit it.
However, you can inherit from a class that has no public members, right?.
The interface issue aside (which I think I agree with you on), it is
possible to design a class that provides only functionality
(implementation details) but not a publicly accessible API (the methods
would be available only to the inheritor).
If you are dealing with a third-party class that you want to incorporate
without exposing to the client of your own class, I agree that's harder.
But as Jon says, there's always containment as an alternative to
inheritance.
I suppose C# could have included the access protection modifier in the
inheritance declaration portion of a class, as C++ does. There are in
fact a variety of things C++ allows that aren't possible or require
workarounds in C#. But I've just come to accept that these are design
decisions made with respect to simplifying the language. I can't say I
fully understand them, but I don't find them all that troublesome either.
What I do find troublesome is when I run across something in C# that _is_
very complicated and/or non-intuitive. It makes it a little harder to
just accept the other simplifications when C# does include things that can
easily cause even an experienced programmer to stumble.
Pete
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;}
......
}
hth
Christof
But yes, an extention of the interface mapping rules, such that members of
an internal interface can map on internal members may be usefull.
Christof
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
Oops, I meant: the implementation of it's members remain internal if they
are implemented *explicitly*.
Christof
What I actually meant was 'explicitly' not 'implicitly'. I mixed them up
somehow.
Christof
In that they can't cast to the interface? Yes, that makes sense.
Jon
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.
>
> Christof
>
I know you can, but adds extra layers of indirection at runtime, entirely
needlessly.
>
> hth
> Christof
>
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
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
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.
Am I missing something?
Christof
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.
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
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.
>
> Christof
>