"friend" level access

Z

Zach

Sorry for the basic question, is there a simple way to achieve the
equivalent of C++ 'friend' level access in C#? I have two classes.
One is an some arbitrary data type I've defined, and another is an
object whose job is to manage objects of this data type. I would like
this manager type to be the only entity with permission to create
instances of this object and update certain types of fields.
Essentially, the constructor and other fields should be private, and
only the Manager class should be allowed to access them.

Clearly there is no "friend" keyword in C#, but is there a way to
achieve a similar effect through some other common pattern? I can
make a new assembly if absolutely necessary and use the internal
specifier, but it seems extremely awkward and overkill.

Thanks
 
D

Doug Semler

Zach said:
Sorry for the basic question, is there a simple way to achieve the
equivalent of C++ 'friend' level access in C#? I have two classes.
One is an some arbitrary data type I've defined, and another is an
object whose job is to manage objects of this data type. I would like
this manager type to be the only entity with permission to create
instances of this object and update certain types of fields.
Essentially, the constructor and other fields should be private, and
only the Manager class should be allowed to access them.

I am not necessarily advocating this particular pattern *BUT* you could do
something like the following. This makes only the "abstract" type public to
all callers, while also keeping your properties that should only be
accessible to the manager type accessible to the manager (since it is a
private subclass). Only thing you have to watch out for is to ensure that
manager functions that accept variables of MyArbitraryType check to ensure
that the type passed in is of one of the types that the manager created,
because this code doesn't prevent something else from deriving off of
MyArbitraryType without some more work....

// This could be an interface as well if you want to define the behavior for
all functions in your instance types...
public abstract class MyArbitraryType
{
public bool PublicProperty
{
get { ... } set { ... }
}
// Other virtual and non virtual and constructors here.
}

public class Manager
{
private class ArbitraryTypeInstance : MyArbitraryType
{
public int ManagerOnlyUpdateableProperty { get { ... } set {
.... } }
}

public MyArbitraryType CreateInstanceOfType()
{
ArbitraryTypeInstance myInstance = new ArbitraryTypeInstance();
// Do other stuff to "manage" type here
return myInstance;
}
}

--
Doug Semler, MCPD
a.a. #705, BAAWA. EAC Guardian of the Horn of the IPU (pbuhh).
The answer is 42; DNRC o-
Gur Hfrarg unf orpbzr fb shyy bs penc gurfr qnlf, abbar rira
erpbtavmrf fvzcyr guvatf yvxr ebg13 nalzber. Fnq, vfa'g vg?
 
C

Chris Dunaway

Sorry for the basic question, is there a simple way to achieve the
equivalent of C++ 'friend' level access in C#? I have two classes.
One is an some arbitrary data type I've defined, and another is an
object whose job is to manage objects of this data type. I would like
this manager type to be the only entity with permission to create
instances of this object and update certain types of fields.
Essentially, the constructor and other fields should be private, and
only the Manager class should be allowed to access them.

Clearly there is no "friend" keyword in C#, but is there a way to
achieve a similar effect through some other common pattern? I can
make a new assembly if absolutely necessary and use the internal
specifier, but it seems extremely awkward and overkill.

Thanks

Have you looked at the internal modifier? internal types are visible
only within its containing assembly.

public class ClassA {
internal ClassA() {
}
}

public class Manager {
public ClassA GetInstance() {
return new ClassA()
}
}
 
P

Peter Duniho

Chris said:
Have you looked at the internal modifier? internal types are visible
only within its containing assembly.

Since he wrote: "I can make a new assembly if absolutely necessary and
use the internal specifier", I suspect he knows about it and how it
works. :)

Personally, I think that if one really wants "friend-like" behavior from
C#, that's actually the right way to do it. I've never really liked
using "friend" in C++ though; much better to design away requirements
that one class has intimate details of another's implementation.

Pete
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
Since he wrote: "I can make a new assembly if absolutely necessary and use
the internal specifier", I suspect he knows about it and how it works. :)

Personally, I think that if one really wants "friend-like" behavior from
C#, that's actually the right way to do it. I've never really liked using
"friend" in C++ though; much better to design away requirements that one
class has intimate details of another's implementation.

In OOP, the unit of data sharing is the "component", not class, and not
assembly. C++ has it right.

One thing you can do in C# is a private member interface, with a public
member class that implements that interface privately. Then only the parent
class can cast the child to that interface and use the private members.

It's a little counter-intuitive to the idea of an interface, but it
accomplishes what you are looking for.
 
P

Peter Duniho

Ben said:
In OOP, the unit of data sharing is the "component", not class, and not
assembly. C++ has it right.

My experience has been that "friend" is abused more in C++ than used
correctly. I don't disagree that there are ways to use it correctly,
but that's not been the norm for the C++ code I've seen that uses
"friend". In my experience, it's unusual to come across well-designed
code, and in poorly-designed code "friend" is generally just used as a
hack to get around some problem in the poorly-designed code.

All that said...

I don't see the difference between C++ friends and C# assemblies. At
best, when used properly the "friend" modifier applies to a component
(as you point out), which is a natural division for an assembly in C#
(where you can use "internal" in the same way as "friend").

If C++ "has it right", then so too does C#. If anything, C# goes one
step further in the right direction, IMHO, by requiring that things that
are part of the same "component" really do wind up built as part of the
same component.

Pete
 
R

Radek Cerny

You touched a nerve there...

c++ has MI as well, which I dearly miss. And public tight-coupling is bad -
true, but 'friend' allows any tight-coupling to be 'private' and
non-abusable.

In any good scalable framework/architecture, a layered scenario always
prohibits the intenal modifier, and where private tight-coupling is
required, the absense of friends force me to make everything public.

So much new stuff is going into c# 3.0 that I am amazed freinds and MI are
excluded. Those have been the top of my list since 1.0.

Cheers
 
P

Peter Duniho

Radek said:
You touched a nerve there...

And you're getting close to doing so.
c++ has MI as well, which I dearly miss.

Many people do, and have said as much in this newsgroup. I don't have
any problem with someone suggesting that they really like MI and miss it
in C#. However, too many MI-philes cross the line and demand that only
with MI can you write "good code", thus implying that those of us that
don't really miss it that much aren't writing good code.
And public tight-coupling is bad -
true, but 'friend' allows any tight-coupling to be 'private' and
non-abusable.

As does "internal".
In any good scalable framework/architecture, a layered scenario always
prohibits the intenal modifier, and where private tight-coupling is
required, the absense of friends force me to make everything public.

I don't understand the above statement. If by "layered scenario" you
mean various components in their own assemblies, then that is true
whether you have a "good scalable framework/architecture" or not. What
does "good scalable framework/architecture" have to do with it?

And what "good scalable framework/architecture" requires "private
tight-coupling" across layers?

Opinions vary, of course, but mine is that if you believe different
components belong in different layers, then they by definition should
not have "private tight-coupling". Conversely, if they need "private
tight-coupling" they should be in the same layer.

No doubt people will disagree, and I'm okay with that. But to the
extent that the people who disagree make statements that imply (or
worse, say so outright) I can't write good code without tightly coupling
components in different layers, that I find EXTREMELY annoying and
unproductive.

Pete
 
J

Jon Skeet [C# MVP]

In any good scalable framework/architecture, a layered scenario always
prohibits the intenal modifier, and where private tight-coupling is
required

Private tight-coupling between different layers? That sounds like a
bad idea to me.
the absense of friends force me to make everything public.

If you want internals to be visible to another assembly, you can use
the InternalsVisibleTo attribute, new to .NET 2.0.

Jon
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
My experience has been that "friend" is abused more in C++ than used
correctly. I don't disagree that there are ways to use it correctly, but
that's not been the norm for the C++ code I've seen that uses "friend".
In my experience, it's unusual to come across well-designed code, and in
poorly-designed code "friend" is generally just used as a hack to get
around some problem in the poorly-designed code.

All that said...

I don't see the difference between C++ friends and C# assemblies. At
best, when used properly the "friend" modifier applies to a component (as
you point out), which is a natural division for an assembly in C# (where
you can use "internal" in the same way as "friend").

If C++ "has it right", then so too does C#. If anything, C# goes one step
further in the right direction, IMHO, by requiring that things that are
part of the same "component" really do wind up built as part of the same
component.

Nonsense. "internal" causes tight coupling between all components
distributed together (one assembly each would be simply ridiculous). Look
at the number of times "internal" is used in System.dll, for example, and
you will realize that 99.9% of these should only be available to a single
 
P

Peter Duniho

Ben said:
Nonsense.

Ah. As ever, you always put things so gently and politely.
"internal" causes tight coupling between all components
distributed together (one assembly each would be simply ridiculous).

"Ridiculous"? Why? Personally, I think it's silly that so many
components are dragged in by a single reference. At the same time, not
everything is which means that on occasion I run into situations where I
have to explicitly reference an assembly, even though I didn't have to
for a wide variety of other unrelated things.

The .NET compartmentalization of components is IMHO overly broad and
inconsistent as well.

You may find a potential requirement to reference multiple assemblies
individually "ridiculous", but I think that's far from a conclusive and
absolute statement. "Simply ridiculous" implies some sort of
obviousness to your conclusion, but that obviousness does not exist at
all. It's a highly subjective issue.

Like your use of the word "nonsense", which is IMHO very insulting when
you use it to describe my own opinions, claiming that restricting
components that need to be "friends" to their own assembly is "simply
ridiculous" is dismissive of other perfectly valid opinions to the contrary.

You may disagree, and that's fine, but I really wish you would behave
yourself better and treat your opinions as the actual opinions that they
are rather than insulting the people you're discussing them with. This
is a non-uncommon pattern in your posts; I would not even bother to
mention it if this were the first time it'd come up.

Even as a programmer, life is not so nearly black-and-white as you seem
to think it is.
Look
at the number of times "internal" is used in System.dll, for example, and
you will realize that 99.9% of these should only be available to a single
other class. A classic example are all the LinkedListNode<T> members.
"internal" is far too broad.

I disagree. The _use_ of "internal" by .NET may be "far too broad".
But that does not mean the keyword itself is. Is it exactly the same as
"friend"? No, obviously not. But it seems to me that it's a perfectly
acceptable alternative.

Pete
 
B

Ben Voigt [C++ MVP]

You may find a potential requirement to reference multiple assemblies
individually "ridiculous", but I think that's far from a conclusive and
absolute statement. "Simply ridiculous" implies some sort of obviousness
to your conclusion, but that obviousness does not exist at all. It's a
highly subjective issue.

Like your use of the word "nonsense", which is IMHO very insulting when
you use it to describe my own opinions, claiming that restricting
components that need to be "friends" to their own assembly is "simply
ridiculous" is dismissive of other perfectly valid opinions to the
contrary.

I would like to apologize for that. I can see how that might be construed
as an insult, I don't wish to insult you, and I hope you will forgive me.

Please understand as well, that your opinion is the one that is exclusive.
You are supporting the view that "internal" is a good enough replacement for
"friend" for everyone, that the restriction is ok in all circumstances.
That strikes me as far more dismissive than my opinion (shared with the OP)
that "friend" behavior is needed in certain circumstances, examples
provided, with no need to remove the existing "internal" access layer.
You may disagree, and that's fine, but I really wish you would behave
yourself better and treat your opinions as the actual opinions that they
are rather than insulting the people you're discussing them with. This is
a non-uncommon pattern in your posts; I would not even bother to mention
it if this were the first time it'd come up.

Even as a programmer, life is not so nearly black-and-white as you seem to
think it is.

You're absolutely right about this, that I find tying encapsulation to file
distribution to be "ridiculous" is my opinion, no more.
I disagree. The _use_ of "internal" by .NET may be "far too broad". But
that does not mean the keyword itself is. Is it exactly the same as
"friend"? No, obviously not. But it seems to me that it's a perfectly
acceptable alternative.

I'm not saying that there is no place for the "internal" keyword, or at
least I don't mean to. What I'm saying is that it is a poor substitute for
"friend". C++ provides both, through the concept of incomplete types and
use of non-public header files. It would be quite useful for .NET to as
well. "internal" is far too broad *for these applications*. There are
other circumstances where it is perfect.

Would you really be happy if each of the reusable blocks in the BCL was in a
separate assembly, requiring a separate DLL file to be located and loaded
from the file system for each, requiring separate per-assembly metadata for
each, preventing string folding, etc?

I think we are agreed on this: that the BCL uses "internal" inappropriately.
Many generally useful things are made internal which should be public, many
things which are not reusable should be made private members of the class
needing them, and quite a few things would be better off as "friend" access,
if there were such a thing.
 
P

Peter Duniho

Ben said:
I would like to apologize for that. I can see how that might be construed
as an insult, I don't wish to insult you, and I hope you will forgive me.

Apology accepted...thank you.
Please understand as well, that your opinion is the one that is exclusive.
You are supporting the view that "internal" is a good enough replacement for
"friend" for everyone, that the restriction is ok in all circumstances.
That strikes me as far more dismissive than my opinion (shared with the OP)
that "friend" behavior is needed in certain circumstances, examples
provided, with no need to remove the existing "internal" access layer.

I'm sorry if my replies made it sound like I felt that "internal" was
exactly equivalent to "friend". I do think that it's obviously not. it
just seemed to me that in this case, it seems like a reasonable
alternative for the stated goal.

I'm not exactly sure what I wrote that wound up sounding like I was
saying "internal" works for everyone in every situation, but whatever I
wrote that came across like that, it wasn't my intent. Sorry for any
confusion.
[...]
I'm not saying that there is no place for the "internal" keyword, or at
least I don't mean to. What I'm saying is that it is a poor substitute for
"friend". C++ provides both, through the concept of incomplete types and
use of non-public header files. It would be quite useful for .NET to as
well. "internal" is far too broad *for these applications*. There are
other circumstances where it is perfect.

Would you really be happy if each of the reusable blocks in the BCL was in a
separate assembly, requiring a separate DLL file to be located and loaded
from the file system for each, requiring separate per-assembly metadata for
each, preventing string folding, etc?

No, that wouldn't make me happy. But it seems to me that "internal",
like "friend", is something to be used sparingly. One hopes that the
issue wouldn't cause too many different assemblies to be required; many
components should be able to be implemented without the use of
"internal" or similar anyway (and besides, there are already specific
examples under the System namespace of components that need to be
referenced explicitly).

I do think it's a bit of a kludge that "internal" is tied to the
assembly. But given that it is, I'm not sure I see any truly huge
problems with the overlap. Optimal? I agree, it's not. But I don't
think it's a fatal flaw either.

Even better would be a .NET design change, possibly impractical at this
point, in which multiple assemblies could be linked statically into a
single DLL. I've always felt that it's somewhat limiting for .NET to
not have a way to combine compiled components into a single DLL or EXE
(and of course, if I'm mistaken about there not being a way -- I haven't
found one yet, but that doesn't mean it doesn't exist -- then obviously
that'd be a way to allow the use of "internal" without having a huge DLL
explosion :) ).
I think we are agreed on this: that the BCL uses "internal" inappropriately.

Yes, I do agree. Much as "friend" is often misused, so too is "internal".

Ironically, as much as people like to debate what language features
should or should not exist, IMHO the language really isn't that
important. Languages can be very nice tools, but in the end no matter
what the language provides or does not provide, there's no substitute
for a programmer who can design simple, workable code.

The fact is, with sufficient discipline, one can accomplish basically
all of the same things a high-level language like C++ or C# offers using
just plain old assembly. And one still needs some level of discipline
to write good C++ or C# code, even with all of the support and
constraints each language offers.

In this particular case, what C# offers is "internal", and I think that
used sparingly as it should be, it shouldn't lead to a great deal of
inefficiency in the form of excessive DLLs.

Pete
 
D

Doug Semler

Even better would be a .NET design change, possibly impractical at this
point, in which multiple assemblies could be linked statically into a
single DLL. I've always felt that it's somewhat limiting for .NET to
not have a way to combine compiled components into a single DLL or EXE
(and of course, if I'm mistaken about there not being a way -- I haven't
found one yet, but that doesn't mean it doesn't exist -- then obviously
that'd be a way to allow the use of "internal" without having a huge DLL
explosion :) ).

There was (still is?) a tool called....what was it? umm.. ILMerge?
That sounds right, yeah.. here it is http://research.microsoft.com/~mbarnett/ILMerge.aspx
It combines multiple assemblies into a single assembly. It even had
options to make public types internal to the final assembly. Dunno if
that's what you're talking about, but we have used it to provide
encapsulation of private assemblies that are shared within the
solution into the final executables. (mainly for obfuscation to tell
the truth).
 
B

Ben Voigt [C++ MVP]

Doug Semler said:
There was (still is?) a tool called....what was it? umm.. ILMerge?
That sounds right, yeah.. here it is
http://research.microsoft.com/~mbarnett/ILMerge.aspx
It combines multiple assemblies into a single assembly. It even had

Not quite right... because the end result is only one assembly, it changes
the meaning of "internal". Similarly using a bunch of netmodules isn't
quite right, because "internal" permits access across module boundaries.
 
A

Arnshea

Nonsense. "internal" causes tight coupling between all components
distributed together (one assembly each would be simply ridiculous). Look
at the number of times "internal" is used in System.dll, for example, and
you will realize that 99.9% of these should only be available to a single
other class. A classic example are all the LinkedListNode<T> members.
"internal" is far too broad.






- Show quoted text -- Hide quoted text -

- Show quoted text -

I think one of the issues that might have led to the dropping of
friend in favor of internal was the concern about versioning.
Internal visibility can't cause "breakage" with a later version of the
assembly since, presumably, the whole assembly is deployed (and built)
as a unit.

If a friend function is defined outside of the dll then deploying a
new version of that dll might break the function.

This strikes me as largely a function of design philosophy
differences, or perhaps priority differences, between the 2
languages. I don't think it's easy to come down clearly on either
side since it's pretty obvious that there are a lot of cases where
friend is very useful (such as, perhaps, the original question).
 
D

Doug Semler

Ben Voigt said:
Not quite right... because the end result is only one assembly, it changes
the meaning of "internal".

But from a programmer's perspective, each component at development time
would only have access to its own internals. It is only at the time of
merging is the "meaning" of internal changed to be internal to the final
assembly. Whether the inputs to ilmerge are a dll or some "static" library
is irrelevant to the final "link" step.

I miss static libraries myself, but I can get "close"
Similarly using a bunch of netmodules isn't quite right, because
"internal" permits access across module boundaries.

I never liked the "netmodule" concept, especially considering it isn't even
supported in the development environment. *I* may know how to compile/link
netmodules, but that doesn't mean I have the time to teach all other 10
devlopers on the project how to do it (nor would they be willing to do
it...they like the drag and drop too much <g>)

--
Doug Semler, MCPD
a.a. #705, BAAWA. EAC Guardian of the Horn of the IPU (pbuhh).
The answer is 42; DNRC o-
Gur Hfrarg unf orpbzr fb shyy bs penc gurfr qnlf, abbar rira
erpbtavmrf fvzcyr guvatf yvxr ebg13 nalzber. Fnq, vfa'g vg?
 
R

Radek Cerny

To answer both you and Peter...

Clarifying what I mean by private tight-coupling: lets say I have an
architecture that has an AppServer, Sessions and Business Objects (all
classes) with Fields inside the BusinessObjects. Almost everything is
virtual and extensible. There is plenty of 'tight-coupling' at the
inner-most layer, for example when a BusinessObject may be passing a result
set to its fields (different classes) or a Session initialising
BusinessObjects from metadata -

(inside Session class)
businessObjectInstance.initailseFromMetadata(xmlElement)

or

(inside BusinessObject class)
myFieldInstance.extractDataFromResultSet(ResultSet)

these methods can not be protected, nor can they be internal as consumers of
this framework (eg authors of varying business systems) require these to be
polymorphic. End result - a whole heap of public functions that are truly
friends - limited to a specific class or hierarchy, but due to the lack of
friends are forced to be public

I'll have a look at InternalsVisibleTo - looks promising.

Radek
 
B

Ben Voigt [C++ MVP]

I think one of the issues that might have led to the dropping of
friend in favor of internal was the concern about versioning.
Internal visibility can't cause "breakage" with a later version of the
assembly since, presumably, the whole assembly is deployed (and built)
as a unit.

If a friend function is defined outside of the dll then deploying a
new version of that dll might break the function.

This strikes me as largely a function of design philosophy
differences, or perhaps priority differences, between the 2
languages. I don't think it's easy to come down clearly on either
side since it's pretty obvious that there are a lot of cases where
friend is very useful (such as, perhaps, the original question).


I think it is a design philosophy difference. The "internal" access
modifier is designed with security in mind. C++ "friend" and Java "package"
access are designed for making software more maintainable. Both are very
useful, but in a world where most code runs with "Full Trust" (i.e.
restricted only by OS access controls on the user) the second is more
critical.

..NET really should be providing both functions. Of course, the second
function doesn't need to be implemented in the runtime, it could be checked
via static code analysis like FxCop.

That might be the ideal solution -- mark such tightly coupling members as
internal, but add a Friend attribute which accepts a Type and have FxCop
check that members with a friend attribute are only accessed by that single
other class. Then add the right syntactic sugar to make languages like C++,
which do have a "friend" keyword, emit the attribute, and maybe even enforce
the rule at compile time.
 
A

Arnshea

...
I think it is a design philosophy difference. The "internal" access
modifier is designed with security in mind. C++ "friend" and Java "package"
access are designed for making software more maintainable. Both are very
useful, but in a world where most code runs with "Full Trust" (i.e.
restricted only by OS access controls on the user) the second is more
critical.

Given what Larry Niven (perhaps among others) pointed out, that
Freedom + Security = K (where K is a constant), this may be one of
those inherent tradeoffs. Full Trust as the norm has been my
experience also. Maybe that's why they loosened it up a bit with the
InternalsVisibleTo attribute in 2.0...
 

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