473,401 Members | 2,127 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,401 software developers and data experts.

Encapsulation


I have two separate classes and would like the members of one class to have
access to the private members of another class. What is the idiomatic C#
solution to this?

I believe C++ would use "friends".

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #1
38 1385
On Fri, 23 May 2008 21:07:16 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
I have two separate classes and would like the members of one class to
have
access to the private members of another class. What is the idiomatic C#
solution to this?

I believe C++ would use "friends".
It doesn't exist in C#.

You can come close with the "internal" keyword. In that access modifier,
every class within the same assembly would be equivalent to being a
"friend", except that private and protected members would still be
hidden. You'd use "internal" on the members that you really want to share.

Alternatively, nested classes have access to private members of the
containing class(es). But IMHO that's only an appropriate solution if the
nested class really makes sense as a nested class. I wouldn't use it just
to address some accessibility issue.

Pete
Jun 27 '08 #2
Jon Harrop wrote:
I have two separate classes and would like the members of one class to have
access to the private members of another class. What is the idiomatic C#
solution to this?

I believe C++ would use "friends".
The typical C# solution would be to put the classes in same
assembly and use "internal" accessibility.

The most similar to C++ friend would be if they use
"internal" accessibility and are in different assemblies, but
use the InternalsVisibleTo attribute - see details at:

http://msdn.microsoft.com/en-us/libr...attribute.aspx

Arne

Jun 27 '08 #3
Arne Vajhøj wrote:
Jon Harrop wrote:
>I have two separate classes and would like the members of one class to
have access to the private members of another class. What is the
idiomatic C# solution to this?

I believe C++ would use "friends".

The typical C# solution would be to put the classes in same
assembly and use "internal" accessibility.
That only restricts accessibility to the million lines of other code that
happens to be in the same assembly, which is such a weak constraint as to
be of no practical use.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #4
Jon Harrop wrote:
Arne Vajhøj wrote:
>Jon Harrop wrote:
>>I have two separate classes and would like the members of one class to
have access to the private members of another class. What is the
idiomatic C# solution to this?

I believe C++ would use "friends".
The typical C# solution would be to put the classes in same
assembly and use "internal" accessibility.

That only restricts accessibility to the million lines of other code that
happens to be in the same assembly, which is such a weak constraint as to
be of no practical use.
I don't think millions of lines of C# code in one assembly
is good at all.

Arne
Jun 27 '08 #5
Arne Vajhøj wrote:
Jon Harrop wrote:
>Arne Vajhøj wrote:
>>Jon Harrop wrote:
I have two separate classes and would like the members of one class to
have access to the private members of another class. What is the
idiomatic C# solution to this?

I believe C++ would use "friends".
The typical C# solution would be to put the classes in same
assembly and use "internal" accessibility.

That only restricts accessibility to the million lines of other code that
happens to be in the same assembly, which is such a weak constraint as to
be of no practical use.

I don't think millions of lines of C# code in one assembly
is good at all.
Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale. Moreover, if
I reduce the size of my assemblies then I increase the probability
that "internal" cannot work because access is required from another
assembly.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #6
Jon Harrop wrote:
I have two separate classes and would like the members of one class to
have access to the private members of another class. What is the idiomatic
C# solution to this?

I believe C++ would use "friends".
Thank you for everyone's responses. The answer appears to be that C# is
unable to express this.

For anyone who is interested, here is a simple example of the kind of
encapsulation that I am referring to (written in OCaml):

module Counter : sig
module Incr : sig
val incr : unit -unit
val get_n : unit -int
end
module Adder : sig
val add : int -unit
end
end = struct
module Incr : sig
val incr : unit -unit
val get_n : unit -int
val set_n : int -unit
end = struct
let n = ref 0
let incr() = incr n
let get_n() = !n
let set_n m =
n := m
end
module Adder = struct
let add m =
Incr.set_n (Incr.get_n() + m)
end
end;;

Note how Counter.Incr.n is used in Counter.Adder.add but is not visible
outside Counter because the Incr module has two different signatures.

Perhaps a better way to explain that in C#-speak is: Counter.Incr.n is
private to Counter.Incr but Counter.Incr.set_n is private to Counter.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #7
Jon Harrop wrote:
Arne Vajhøj wrote:
>Jon Harrop wrote:
>>Arne Vajhøj wrote:
Jon Harrop wrote:
I have two separate classes and would like the members of one class to
have access to the private members of another class. What is the
idiomatic C# solution to this?
>
I believe C++ would use "friends".
The typical C# solution would be to put the classes in same
assembly and use "internal" accessibility.
That only restricts accessibility to the million lines of other code that
happens to be in the same assembly, which is such a weak constraint as to
be of no practical use.
I don't think millions of lines of C# code in one assembly
is good at all.

Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale.
It scales fine.

But it means that the source code and the assemblies are not
independent.
Moreover, if
I reduce the size of my assemblies then I increase the probability
that "internal" cannot work because access is required from another
assembly.
Well - we have give you the solution to that problem. If you choose
not to use that, then it is your problem not .NET's.

Arne
Jun 27 '08 #8
Arne Vajhøj wrote:
Jon Harrop wrote:
>Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale.

It scales fine.
If it scaled then I would be able to nest assemblies and mark data
as "internal" to the current or any parent assembly. But I cannot =it
does not scale.

Perhaps you mean that it is still possible to write monumental code bases in
the absence of decent encapsulation mechanisms. I cannot disagree with
that.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #9
Jon Harrop wrote:
Arne Vajhøj wrote:
>Jon Harrop wrote:
>>Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale.
It scales fine.

If it scaled then I would be able to nest assemblies and mark data
as "internal" to the current or any parent assembly. But I cannot =it
does not scale.

Perhaps you mean that it is still possible to write monumental code bases in
the absence of decent encapsulation mechanisms. I cannot disagree with
that.
I assume you mean "I cannot agree" or "I disagree".

If you look out in the real world, then you will see that
somehow people are able to write software with lots
of assemblies without the ability to have a "nested
assembly" mechanism.

Arne

Jun 27 '08 #10
On Sat, 24 May 2008 15:34:23 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>I don't think millions of lines of C# code in one assembly
is good at all.

Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale.
That word "scale". You seem to think it means something other than what
it means.
Moreover, if
I reduce the size of my assemblies then I increase the probability
that "internal" cannot work because access is required from another
assembly.
Huh? If access is required from another assembly, you add the attribute
Arne suggested, so that the other assembly has access.

I agree it's not a perfect solution, but IMHO "friend" is overused
anyway. Most of the time I see someone wanting to make their classes
"friends", they are heading down the wrong path in the first place.

In any case, as has been explained: this is what C# offers. If you think
it's completely unsuitable to your needs, you need to use a different
language. C++ still has "friend" and you can use that with .NET if you're
still trying to write a .NET program.

Pete
Jun 27 '08 #11
Arne Vajhøj wrote:
Jon Harrop wrote:
>Perhaps you mean that it is still possible to write monumental code bases
in the absence of decent encapsulation mechanisms. I cannot disagree with
that.

I assume you mean "I cannot agree" or "I disagree".
No, I meant what I said. Consider it roughly equivalent to "I agree with
that".
If you look out in the real world, then you will see that
somehow people are able to write software with lots
of assemblies without the ability to have a "nested
assembly" mechanism.
Absolutely. Many of our competitors are bumbling around with enormous
Fortran 77 codebases that have no encapsulation or high-level structure at
all.

Tolerating the same deficiencies would mean commercial suicide for us.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #12
Jon Harrop wrote:
module Counter : sig
module Incr : sig
val incr : unit -unit
val get_n : unit -int
end
module Adder : sig
val add : int -unit
end
end = struct
module Incr : sig
val incr : unit -unit
val get_n : unit -int
val set_n : int -unit
end = struct
let n = ref 0
let incr() = incr n
let get_n() = !n
let set_n m =
n := m
end
module Adder = struct
let add m =
Incr.set_n (Incr.get_n() + m)
end
end;;
I just had an idea of how it might be possible to workaround this deficiency
in C#. You can try to rewrite your code such that C#'s notion of "private
to this class only" is sufficient by pushing data up the class hierarchy.
Then you can pretend the data is actually in its logical place low in the
class hierarchy by implementing a property in that class.

I don't think that covers the general case but it might be sufficient for my
purposes. Our internal code will be hideous but at least it will present a
usable API for our customers.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #13
Jon Harrop wrote:
Arne Vajhøj wrote:
>If you look out in the real world, then you will see that
somehow people are able to write software with lots
of assemblies without the ability to have a "nested
assembly" mechanism.

Absolutely. Many of our competitors are bumbling around with enormous
Fortran 77 codebases that have no encapsulation or high-level structure at
all.

Tolerating the same deficiencies would mean commercial suicide for us.
I was talking about .NET code even though I also know about
some Fortran code.

But one size does not fit all. Maybe C# and .NET is not
suitable for your apps.

Arne
Jun 27 '08 #14
Arne Vajhøj wrote:
Jon Harrop wrote:
>Absolutely. Many of our competitors are bumbling around with enormous
Fortran 77 codebases that have no encapsulation or high-level structure
at all.

Tolerating the same deficiencies would mean commercial suicide for us.

I was talking about .NET code even though I also know about
some Fortran code.

But one size does not fit all. Maybe C# and .NET is not
suitable for your apps.
Fortunately there are other .NET languages. Unfortunately, the all share
deficiency AFAIK...

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #15
On Sat, 24 May 2008 17:30:14 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
[...]
>But one size does not fit all. Maybe C# and .NET is not
suitable for your apps.

Fortunately there are other .NET languages. Unfortunately, the all share
deficiency AFAIK...
You started this thread by writing "I believe C++ would use "friends"".
Assuming that's actually the behavior you want, why not just use C++?

Pete
Jun 27 '08 #16
Jon Harrop wrote:
I just had an idea of how it might be possible to workaround this
deficiency in C#. You can try to rewrite your code such that C#'s notion
of "private to this class only" is sufficient by pushing data up the class
hierarchy. Then you can pretend the data is actually in its logical place
low in the class hierarchy by implementing a property in that class.

I don't think that covers the general case but it might be sufficient for
my purposes. Our internal code will be hideous but at least it will
present a usable API for our customers.
Actually that doesn't help at all: it is just resorting to completely
unstructured programming because you still have no way to restrict
accessibility to the properties.

So forget that... :-(

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #17
Peter Duniho wrote:
You started this thread by writing "I believe C++ would use "friends"".
Assuming that's actually the behavior you want...
That is not the behaviour I want. I only drew the comparison because I hoped
people here might be familiar with C++. My later comparison with OCaml is
precise.

The problem is essentially that "private" can only be used to mean "private
to the current class" in C# and there is no way to express "private to my
parent class" and so on.
why not just use C++?
The obvious reasons:

.. It is not practically feasible to rewrite the code base in another
language.

.. C++ has other (far more serious) deficiencies.

.. Cross-language development would probably introduce more problems than it
would solve.

etc.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #18
On Sat, 24 May 2008 18:10:31 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
Peter Duniho wrote:
>You started this thread by writing "I believe C++ would use "friends"".
Assuming that's actually the behavior you want...

That is not the behaviour I want. I only drew the comparison because I
hoped
people here might be familiar with C++. My later comparison with OCaml is
precise.

The problem is essentially that "private" can only be used to mean
"private
to the current class" in C# and there is no way to express "private to my
parent class" and so on.
That's not exactly true. As I mentioned earlier, nested classes have
access to private members in their containing classes.

Whether that addresses your question or not, I can't say. I don't know
OCaml and I'm still trying to decipher that example (honestly, what makes
you think you can post an example in an obscure language like that to a C#
newsgroup and think it's an effective way of getting your point across is
beyond me), so maybe it doesn't.
>why not just use C++?

The obvious reasons:
Forgive me if I don't see them as obvious, especially given your original
question.
. It is not practically feasible to rewrite the code base in another
language.
You'd only need to rewrite the parts that need this functionality.
. C++ has other (far more serious) deficiencies.
Every language is a compromise. You need to pick what's most important to
you.
. Cross-language development would probably introduce more problems than
it
would solve.
I doubt that. Once you've got a compiled, managed assembly, it doesn't
really matter what language you wrote the code in.

Anyway, I'll keep looking at that OCaml example and try to figure out
exactly what it is you're trying to do.

Pete
Jun 27 '08 #19
Peter Duniho wrote:
On Sat, 24 May 2008 15:34:23 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>>I don't think millions of lines of C# code in one assembly
is good at all.

Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale.

That word "scale". You seem to think it means something other than what
it means.
I mean "scale" in the mathematical sense: as program size increases the
utility of that approach tends to zero.
>Moreover, if
I reduce the size of my assemblies then I increase the probability
that "internal" cannot work because access is required from another
assembly.

Huh? If access is required from another assembly, you add the attribute
Arne suggested, so that the other assembly has access.
Sure but you are still trying to use a flat sequence of assemblies to
represent a hierarchy of constraints.
I agree it's not a perfect solution, but IMHO "friend" is overused
anyway. Most of the time I see someone wanting to make their classes
"friends", they are heading down the wrong path in the first place.
I am actually translating from ML and not C++. In ML, you can refine
interfaces (called signatures) hierarchically and the result is clear,
simple and scales flawlessly.
In any case, as has been explained: this is what C# offers. If you think
it's completely unsuitable to your needs, you need to use a different
language. C++ still has "friend" and you can use that with .NET if you're
still trying to write a .NET program.
I just want to be absolutely sure that there isn't some whizz-bang feature
in C# that beautifully solves that problem but that I had overlooked.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #20
On Sat, 24 May 2008 15:35:12 -0700, Jon Harrop <jo*@ffconsultancy.com
wrote:
Jon Harrop wrote:
>I have two separate classes and would like the members of one class to
have access to the private members of another class. What is the
idiomatic
C# solution to this?

I believe C++ would use "friends".

Thank you for everyone's responses. The answer appears to be that C# is
unable to express this.

For anyone who is interested, here is a simple example of the kind of
encapsulation that I am referring to (written in OCaml):
My first thought is: inasmuch as one can say that different languages
exist for different reasons, it seems to me that just because you can do
something in a language like OCaml, it's not clear you should expect to be
able to do it in some other language. At the very least, there seems to
be some greater implicit connection between the OCaml modules you posted
than there would be between classes in C#.

That said, I agree that it doesn't seem like this has anything to do with
the functional aspect of OCaml, but rather just how accessibility is
determined. With that in mind, some other thoughts:
[...]
Note how Counter.Incr.n is used in Counter.Adder.add but is not visible
outside Counter because the Incr module has two different signatures.

Perhaps a better way to explain that in C#-speak is: Counter.Incr.n is
private to Counter.Incr but Counter.Incr.set_n is private to Counter.
With respect to the code you posted, my first observation is that I'm not
really clear why you put the actual counter in your Incr module. If Incr
was defined to just be the thing that does the incrementing, you could put
the counter itself in the Counter module. From an OOP point of view, this
makes more sense to me. YMMV.

If you do that, then you solve the accessibility issue simply by moving
the counter to a place where both nested classes can get at it:

public class Counter
{
private int n { get; set; }

public class Incr
{
public void incr(Counter counter) { counter.n += 1; }
}

public class Adder
{
public void add(Counter counter, int m) { counter.n += m;}
}
}

Alternatively, you could use interfaces to keep part of your Incr class
private, even as you make some of it public. Here is an example of a
Counter class that contains a private implementation of Incr that is
accessible to Adder, but which implements the public interface IIncr that
only publishes the incr() method:

public interface IIncr
{
void incr();
}

public class Counter
{
public Counter()
{
Incr = new IncrClass();
Adder = new AdderClass(this);
}

public readonly AdderClass Adder;
private readonly IncrClass Incr;
public IIncr IIncr { get { return Incr; } }

// This class is private, so that only other Counter members
// can see the entire API
private class IncrClass : IIncr
{
public int n { get; set; }

public void incr() { n += 1; }
}

// This class could be private too, but since we're not trying
// to hide anything, making it public saves having us need to
// make another interface declaration :)
public class AdderClass
{
public AdderClass(Counter counter)
{
this.counter = counter;
}

private readonly Counter counter;

public void add(int m) { counter.Incr.n += m; }
}
}

Since I'm not fluent in OCaml, I don't know for sure that either of the
above are similar enough to what you posted. If not, then I would suggest
using something other than OCaml to demonstrate your point. Even if you
simply posted C# that doesn't compile, but which is what you'd _expect_,
as long as you also explain what the part of the C# code that doesn't
compile is supposed to be doing, I think that'd be a better example thana
language that practically none of us have ever used. :)

Pete
Jun 27 '08 #21
Peter Duniho wrote:
On Sat, 24 May 2008 18:10:31 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>Peter Duniho wrote:
>>You started this thread by writing "I believe C++ would use "friends"".
Assuming that's actually the behavior you want...

That is not the behaviour I want. I only drew the comparison because I
hoped
people here might be familiar with C++. My later comparison with OCaml is
precise.

The problem is essentially that "private" can only be used to mean
"private
to the current class" in C# and there is no way to express "private to my
parent class" and so on.

That's not exactly true. As I mentioned earlier, nested classes have
access to private members in their containing classes.
Exactly, yes.

Starting from my OCaml solution you can identify the more globally private
definitions in Incr ("n" and "set_n") and push the them up the class
hierarchy without changing the API. In this case, move them into Counter:

module Counter : sig
module Incr : sig
val incr : unit -unit
val get_n : unit -int
end
module Adder : sig
val add : int -unit
end
end = struct
let n = ref 0
let set_n m =
n := m
module Incr = struct
let incr() = incr n
let get_n() = !n
end
module Adder = struct
let add m =
set_n (Incr.get_n() + m)
end
end;;

From an external point of view this provides exactly the same interface as
my original solution but there is now only one global interface for "Incr"
so this solution can be expressed directly in C#.

However, the logically related definitions "n", "set_n" and "get_n" that
were nicely encapsulated in the Incr module are now scattered across the
class hierarchy, their locations dictated by how "private" they are.
Whether that addresses your question or not, I can't say. I don't know
OCaml and I'm still trying to decipher that example (honestly, what makes
you think you can post an example in an obscure language like that to a C#
newsgroup and think it's an effective way of getting your point across is
beyond me), so maybe it doesn't.
I'm sorry but I can see no better way to convey the problem.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #22
Peter Duniho wrote:
On Sat, 24 May 2008 15:35:12 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>For anyone who is interested, here is a simple example of the kind of
encapsulation that I am referring to (written in OCaml):

My first thought is: inasmuch as one can say that different languages
exist for different reasons, it seems to me that just because you can do
something in a language like OCaml, it's not clear you should expect to be
able to do it in some other language. At the very least, there seems to
be some greater implicit connection between the OCaml modules you posted
than there would be between classes in C#.

That said, I agree that it doesn't seem like this has anything to do with
the functional aspect of OCaml, but rather just how accessibility is
determined.
Exactly, yes. This is a characteristic of the module system and has nothing
to do with functional programming.
With that in mind, some other thoughts:
>[...]
Note how Counter.Incr.n is used in Counter.Adder.add but is not visible
outside Counter because the Incr module has two different signatures.

Perhaps a better way to explain that in C#-speak is: Counter.Incr.n is
private to Counter.Incr but Counter.Incr.set_n is private to Counter.

With respect to the code you posted, my first observation is that I'm not
really clear why you put the actual counter in your Incr module. If Incr
was defined to just be the thing that does the incrementing, you could put
the counter itself in the Counter module. From an OOP point of view, this
makes more sense to me. YMMV.
Yes. You would almost certainly remove Incr and Adder entirely but that is
changing the problem rather than solving it! :-)
...
public interface IIncr
{
void incr();
}

public class Counter
{
public Counter()
{
Incr = new IncrClass();
Adder = new AdderClass(this);
}

public readonly AdderClass Adder;
private readonly IncrClass Incr;
public IIncr IIncr { get { return Incr; } }

// This class is private, so that only other Counter members
// can see the entire API
private class IncrClass : IIncr
{
public int n { get; set; }

public void incr() { n += 1; }
}

// This class could be private too, but since we're not trying
// to hide anything, making it public saves having us need to
// make another interface declaration :)
public class AdderClass
{
public AdderClass(Counter counter)
{
this.counter = counter;
}

private readonly Counter counter;

public void add(int m) { counter.Incr.n += m; }
}
}
This does not expose the correct API because the counter cannot be read from
outside the Counter class. However, I've been fiddling with this for the
past hour and derived the following solution from it which I think is
correct:

public class Counter
{
private int n { get; set; }

public Counter()
{
Incr = new IncrClass(this);
Adder = new AdderClass(this);
}

public readonly AdderClass Adder;
public readonly IncrClass Incr;

public class IncrClass
{
public IncrClass(Counter counter) { this.counter = counter; }
private readonly Counter counter;
public int n { get { return counter.n; } }
public void incr() { counter.n += 1; }
}

public class AdderClass
{
public AdderClass(Counter counter) { this.counter = counter; }
private readonly Counter counter;
public void add(int m) { counter.n += m; }
}
}

This preserves my original API, with a getter and incrementer for the
counter in Counter.Incr and an adder in Adder. The counter itself has been
pushed up from Incr into Counter to make it private over a wider area
(including Adder). The critical point is that a property in Counter.Incr is
used to make it look as if the counter is still there from the point of
view of everything outside Counter.

So I think this satisfies all of my requirements and, although it requires
duplication, I think it is much cleaner than using "internal" and trying to
decompose a big program into separate assemblies to achieve the same
effect.

In general terms, you take ML code with refined interfaces and rewrite it by
moving definitions to be as global as possible without widening their
accessibility. Then you implement a property/member where they were to make
it look as if they never moved.
Since I'm not fluent in OCaml, I don't know for sure that either of the
above are similar enough to what you posted. If not, then I would suggest
using something other than OCaml to demonstrate your point. Even if you
simply posted C# that doesn't compile, but which is what you'd _expect_,
as long as you also explain what the part of the C# code that doesn't
compile is supposed to be doing, I think that'd be a better example than a
language that practically none of us have ever used. :)
Actually it looks like OCaml turned out to be the best representation here.
Thanks very much for your help!

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #23
On Sat, 24 May 2008 20:21:39 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
[...]
This does not expose the correct API because the counter cannot be read
from
outside the Counter class. However, I've been fiddling with this for the
past hour and derived the following solution from it which I think is
correct: [snip]
You could have just changed the IncrClass property and associated
interface so that the getter was public. Then the counter could have
stayed in the IncrClass (assuming that was important to you). Or for that
matter simply used a different name for the internal/shared/whatever
property than the external/public/whatever property, the latter having
only a getter, and the former being as in my example.
[...]
Actually it looks like OCaml turned out to be the best representation
here.
I guess that depends on your point of view. From where I'm sitting, your
OCaml example was VERY difficult to turn into something that explained
your problem.

No doubt it was very easy for you to create the example, so from your
point of view, you got what you wanted with a minimum of effort on your
part. But that doesn't mean it was the best representation.
Thanks very much for your help!
You're welcome. :)

Pete
Jun 27 '08 #24
Peter Duniho wrote:
On Sat, 24 May 2008 20:21:39 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>This does not expose the correct API because the counter cannot be read
from
outside the Counter class. However, I've been fiddling with this for the
past hour and derived the following solution from it which I think is
correct: [snip]

You could have just changed the IncrClass property and associated
interface so that the getter was public. Then the counter could have
stayed in the IncrClass (assuming that was important to you). Or for that
matter simply used a different name for the internal/shared/whatever
property than the external/public/whatever property, the latter having
only a getter, and the former being as in my example.
How could you make the setter accessible to AdderClass (i.e. it cannot be
private to IncrClass) but inaccessible from outside Counter (i.e. it cannot
be public either) without moving it out of IncrClass?

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #25
On Sun, 25 May 2008 03:58:42 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
How could you make the setter accessible to AdderClass (i.e. it cannot be
private to IncrClass) but inaccessible from outside Counter (i.e. it
cannot
be public either) without moving it out of IncrClass?
The setter is already accessible to AdderClass without being accessible
outside Counter. So I think your real question is how to make the
_getter_ accessible outside Counter without making the setter also
accessible. And the answer is, the same way we made the incr() method
accessible without making other parts of IncrClass public: add it (the
getter, and only the getter) to the interface.

In the example I posted, just one more line is needed to allow retrieval
of the actual counter value. To the interface declaration, add:

int n { get; }

Nothing else needed to change, and you would then be able to retrieve "n"
from Counter (via IIncr, same as the "incr()" method).

In fact, the more I look at your OCaml example, the more I think that
interfaces are always going to be the natural C# way to address this
"sig/struct" business in OCaml. If I understand that correctly, the "sig"
part is how the module looks to the outside world, and the "struct" part
is the actual implementation, visible to peers within a module. This is
exactly what the interface/implementation stuff does in C#. The interface
is like the OCaml sig, and the implementation is like the OCaml struct.

Starting with some nested-class implementation that you only want part of
its public API (that is, the part that's public to its peers in the
containing class) to be public to the outside world, you simply create an
interface that describes the parts of the nested-class that you want to be
public to the outside world and leave everything else out.

Pete
Jun 27 '08 #26
Jon Harrop wrote:
Peter Duniho wrote:
>You started this thread by writing "I believe C++ would use "friends"".
Assuming that's actually the behavior you want...

That is not the behaviour I want. I only drew the comparison because I hoped
people here might be familiar with C++. My later comparison with OCaml is
precise.

The problem is essentially that "private" can only be used to mean "private
to the current class" in C# and there is no way to express "private to my
parent class" and so on.
>why not just use C++?

The obvious reasons:

. It is not practically feasible to rewrite the code base in another
language.

. C++ has other (far more serious) deficiencies.

. Cross-language development would probably introduce more problems than it
would solve.
And it should be noted that friend is not valid in managed types
in C++.

Arne
Jun 27 '08 #27
Jon Harrop wrote:
Peter Duniho wrote:
>On Sat, 24 May 2008 15:34:23 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>>>I don't think millions of lines of C# code in one assembly
is good at all.
Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale.
That word "scale". You seem to think it means something other than what
it means.

I mean "scale" in the mathematical sense: as program size increases the
utility of that approach tends to zero.
Maybe eventually.

But there is no indication of it happening in the .NET framework.

So I would say that it is only a potential problem if you plan
on developing something a couple of magnitudes larger than the
..NET framework.

Arne
Jun 27 '08 #28
Arne Vajhøj wrote:
Jon Harrop wrote:
>Peter Duniho wrote:
>>On Sat, 24 May 2008 15:34:23 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
I don't think millions of lines of C# code in one assembly
is good at all.
Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale.
That word "scale". You seem to think it means something other than what
it means.

I mean "scale" in the mathematical sense: as program size increases the
utility of that approach tends to zero.

Maybe eventually.

But there is no indication of it happening in the .NET framework.
What makes you think that?

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #29
On May 24, 12:07 am, Jon Harrop <j...@ffconsultancy.comwrote:
I have two separate classes and would like the members of one class to have
access to the private members of another class. What is the idiomatic C#
solution to this?

I believe C++ would use "friends".

--
Dr Jon D Harrop, Flying Frog Consultancyhttp://www.ffconsultancy.com/products/?u
If you let both classes inherit from a third superclass, you can use
"protected" to let them see each other's data (I think). I would not
do that, however, without documenting it prominently.
Jun 27 '08 #30
Jon Harrop wrote:
Arne Vajhøj wrote:
>Jon Harrop wrote:
>>Peter Duniho wrote:
On Sat, 24 May 2008 15:34:23 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>I don't think millions of lines of C# code in one assembly
>is good at all.
Whether I have one line or a million lines, the idea of restricting
accessibility to a single-level (the assembly) does not scale.
That word "scale". You seem to think it means something other than what
it means.
I mean "scale" in the mathematical sense: as program size increases the
utility of that approach tends to zero.
Maybe eventually.

But there is no indication of it happening in the .NET framework.

What makes you think that?
The usability of .NET is nowhere near zero.

Arne
Jun 27 '08 #31
Arne Vajhøj wrote:
Jon Harrop wrote:
>Arne Vajhøj wrote:
>>Jon Harrop wrote:
Peter Duniho wrote:
On Sat, 24 May 2008 15:34:23 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>>I don't think millions of lines of C# code in one assembly
>>is good at all.
>Whether I have one line or a million lines, the idea of restricting
>accessibility to a single-level (the assembly) does not scale.
That word "scale". You seem to think it means something other than
what it means.
I mean "scale" in the mathematical sense: as program size increases the
utility of that approach tends to zero.
Maybe eventually.

But there is no indication of it happening in the .NET framework.

What makes you think that?

The usability of .NET is nowhere near zero.
Sure. That says nothing of the utility of this workaround though.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #32
harborsparrow wrote:
If you let both classes inherit from a third superclass, you can use
"protected" to let them see each other's data (I think). I would not
do that, however, without documenting it prominently.
I believe a lack of multiple inheritance means that cannot work in general
but the idiomatic C# workaround is to use interfaces however C# does not
yet support access modifiers in interfaces. Is that correct?

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #33
On Tue, 27 May 2008 06:28:53 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
harborsparrow wrote:
>If you let both classes inherit from a third superclass, you can use
"protected" to let them see each other's data (I think). I would not
do that, however, without documenting it prominently.

I believe a lack of multiple inheritance means that cannot work in
general
but the idiomatic C# workaround is to use interfaces however C# does not
yet support access modifiers in interfaces. Is that correct?
Technically, yes. But it's not clear what you mean. All interface
members are "public", but interfaces themselves need not be. You can use
the access modifier on the interface itself, nesting the interface as
appropriate, to control access to specific parts of a class.

That said, I already provided a reply to your most recent problem, showing
you how to solve it. At least for the extant example, it doesn't seem as
though having access modifiers within an interface would be needed or
useful in any case.

Pete
Jun 27 '08 #34
Peter Duniho wrote:
On Tue, 27 May 2008 06:28:53 -0700, Jon Harrop <jo*@ffconsultancy.com>
wrote:
>harborsparrow wrote:
>>If you let both classes inherit from a third superclass, you can use
"protected" to let them see each other's data (I think). I would not
do that, however, without documenting it prominently.

I believe a lack of multiple inheritance means that cannot work in
general
but the idiomatic C# workaround is to use interfaces however C# does not
yet support access modifiers in interfaces. Is that correct?

Technically, yes. But it's not clear what you mean. All interface
members are "public", but interfaces themselves need not be. You can use
the access modifier on the interface itself, nesting the interface as
appropriate, to control access to specific parts of a class.
I see. So you might need many separate interfaces for any given class.
That said, I already provided a reply to your most recent problem, showing
you how to solve it. At least for the extant example, it doesn't seem as
though having access modifiers within an interface would be needed or
useful in any case.
Perhaps it would be more concise?

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #35
Jon Harrop wrote:
Arne Vajhøj wrote:
>Jon Harrop wrote:
>>Arne Vajhøj wrote:
Jon Harrop wrote:
Peter Duniho wrote:
>On Sat, 24 May 2008 15:34:23 -0700, Jon Harrop <jo*@ffconsultancy.com>
>wrote:
>>>I don't think millions of lines of C# code in one assembly
>>>is good at all.
>>Whether I have one line or a million lines, the idea of restricting
>>accessibility to a single-level (the assembly) does not scale.
>That word "scale". You seem to think it means something other than
>what it means.
I mean "scale" in the mathematical sense: as program size increases the
utility of that approach tends to zero.
Maybe eventually.

But there is no indication of it happening in the .NET framework.
What makes you think that?
The usability of .NET is nowhere near zero.

Sure. That says nothing of the utility of this workaround though.
It says that the problem you describe does not seem to
have any effect on the total product.

Arne
Jun 27 '08 #36
Arne Vajhøj wrote:
Jon Harrop wrote:
>Arne Vajhøj wrote:
>>Jon Harrop wrote:
Arne Vajhøj wrote:
Jon Harrop wrote:
>Peter Duniho wrote:
>>On Sat, 24 May 2008 15:34:23 -0700, Jon Harrop
>><jo*@ffconsultancy.comwrote:
>>>>I don't think millions of lines of C# code in one assembly
>>>>is good at all.
>>>>
>>>Whether I have one line or a million lines, the idea of restricting
>>>accessibility to a single-level (the assembly) does not scale.
>>>
>>That word "scale". You seem to think it means something other than
>>what it means.
>>
>I mean "scale" in the mathematical sense: as program size increases
>the utility of that approach tends to zero.
>
Maybe eventually.
>
But there is no indication of it happening in the .NET framework.
What makes you think that?

The usability of .NET is nowhere near zero.

Sure. That says nothing of the utility of this workaround though.

It says that the problem you describe does not seem to have any effect on
the total product.
No, you have simply made a sequence of unrelated statements, none of which
have any bearing on the problem I described.

Your statement "the usability of .NET is nowhere near zero" obviously does
not imply that "there is no indication of it happening in the .NET
framework". Moreover, it has nothing to do with the problem I described.

Your statement "there is no indication of it happening in the .NET
framework" is a claim that you have failed to observe something. You cannot
draw any strong conclusions from failing to find evidence, particularly
when there is no evidence that you have even looked.

By the same logic, "the usability of LAPACK is nowhere near zero" says that
garbage collection does not seem to have any effect on products. That is
absurd, of course.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #37
Jon Harrop wrote:
I am actually translating from ML and not C++. In ML, you can refine
interfaces (called signatures) hierarchically and the result is clear,
simple and scales flawlessly.
I just want to be absolutely sure that there isn't some whizz-bang feature
in C# that beautifully solves that problem but that I had overlooked.
Short answer: C# (similarly to Java) simply doesn't provide hierarchical
modules. Classes and assemblies are all you get.

Hierarchically composed modules would be nice and all, but all us folks
in the .NET and Java worlds have been getting along fairly OK without
them up until now.

-- Barry

--
http://barrkel.blogspot.com/
Jun 27 '08 #38
Barry Kelly wrote:
Jon Harrop wrote:
>I am actually translating from ML and not C++. In ML, you can refine
interfaces (called signatures) hierarchically and the result is clear,
simple and scales flawlessly.
>I just want to be absolutely sure that there isn't some whizz-bang
feature in C# that beautifully solves that problem but that I had
overlooked.

Short answer: C# (similarly to Java) simply doesn't provide hierarchical
modules. Classes and assemblies are all you get.

Hierarchically composed modules would be nice and all, but all us folks
in the .NET and Java worlds have been getting along fairly OK without
them up until now.
Right, thanks.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
Jun 27 '08 #39

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: .pd. | last post by:
If I have a control that adds itself to its container, does that break encapsulation? Is it a bad thing? Here's what I mean: public class fred { public barny b; public fred() {
3
by: K.K. | last post by:
Consider the following code: >>>>>>>>>>> // Define an empty class public class ZorgleCollection : Dictionary<string, Zorgle> { } // Somewhere outside ZorgleCollection:
3
by: enchantingdb | last post by:
I have an exam tomorrow that covers the perceived advantages and disadvantages of object oriented programming, in particular polymorphism, inheritance and encapsulation. I know the advantages but...
6
by: William H. Burling | last post by:
I am not sure I understand encapsulation. I thought that one of the objectives in OOPs is to hide data structures from other objects so that they did not have to know how to unpack them. ...
5
by: jmsantoss | last post by:
Hi, This is a design question. I have a class named "DataBuffer" that stores some data. After "DataBuffer" is created it can not be modified. All the methods of "DataBuffer" are const as data...
47
by: Roger Lakner | last post by:
I often see operator implemented something like this: class Foo { ... }; class FooList { public: const Foo& operator (unsigned index) const {return array;}; Foo& operator (unsigned index) ...
32
by: bluejack | last post by:
Ahoy: For as long as I've been using C, I've vacillated on the optimal degree of encapsulation in my designs. At a minimum, I aggregate data and code that operate on that data into classlike...
16
by: copx | last post by:
I have recently read "Everything you ever wanted to know about C types" by Peter Seebach (1), and learned about incomplete types. Now, I realise the value of encapsulation, but I wonder whether it...
2
by: subramanian100in | last post by:
Is my following understanding correct ? Data abstraction means providing the interface - that is, the set of functions that can be called by the user of a class. Information hiding means...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.