0

Given the available accessibility Levels, is there any pattern or proper approach to make class A accessible only from class B and C and vice versa, where there is no inheritance relation between class A, class B and class C? (Preferrably at compile time)

A,B and C are siblings and are located in the same namespace.

So far, the only thing that comes to mind is:

  • Using reflection to determine calling class and throwing exceptions (Runtime)
  • Nest classes (using a base class) and use protected modifier

The latter seems to be the best approach, but is there any other way? I am looking for something like InternalsVisibleTo but inside an assembly.

Marcus
  • 8,230
  • 11
  • 61
  • 88
  • Does "friend" exist? Would that even do what he's asking? – Almo Oct 01 '15 at 13:49
  • @Almo `Friend` is the VB equivalent of `internal` – James Thorpe Oct 01 '15 at 13:49
  • @JamesThorpe Cannot always trust that classes are not "_referenced elsewhere_", and so I think I am better of just going with a base class solution. I wish to avoid projects containing three classes. Thanks! – Marcus Oct 01 '15 at 13:53
  • What'e the _external_ usage? Surely something other than A, B, or C must be able to access at least one of them. – D Stanley Oct 01 '15 at 13:55
  • Naturally, and they will also have different names. Provided is a simplified example of course, and maybe you are getting at nesting private classes within the externally available class? – Marcus Oct 01 '15 at 13:58

2 Answers2

2

Well you could create a containing class that has the three classes as private nested classes:

public class O
{
    private class A { private void Test() {B b = new B(); C c = new C(); }}
    private class B { private void Test() {A a = new A(); C c = new C(); }}
    private class C { private void Test() {B b = new B(); A a = new A(); }}
}

public class Hacker
{
    O.A a = new O.A();  // fail
}

Note that nesting classes does not imply any sort of inheritance relationship - it's used purely for accessibility purposes.

But what's the point of the three classes if they can't be accessed outside of their little circle? What does use those classes?

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • 1
    "But what's the point of the three classes if they can't be accessed outside of their little circle" They could implement interfaces, but you would like others not to construct or reference them directly. – weston Oct 01 '15 at 14:04
  • 1
    @weston but _something_ has to create them. The way the question is worded is sounds like these three are on a deserted island with no communication to or from the mainland. – D Stanley Oct 01 '15 at 14:09
  • Well yes I agree, you need something non-private that owns them, like `O` in your example. – weston Oct 01 '15 at 14:12
  • The only reason I would like to do this is to _box_ the functionality and make them (the classes) inaccessible from "unwanted" parties. My example is small and does not detail my real situation enough but because of privacy constraints I cannot post the code. I guess this (nesting classes) would be the best way to go... – Marcus Oct 01 '15 at 14:18
1

The strictest you can get (whilst still being able to see it from other classes) is internal but then as you know, any class in that assembly can see that class.

It would be nice to have something like package private in Java, which is private except to other members of that package (namespace) but alas C# doesn't have that.

However you could arrange your assemblies to enforce this:

Instead of:

Assembly
   -internal A
   -B (uses A)
   -C (uses A)
   -D (uses the public classes of Assembly1, but can also see A)

Separate them to:

Assembly1
   -internal A
   -B (uses A)
   -C (uses A)
Assembly2
   -references Assembly1
   -D (uses the public classes of Assembly1, can't see A)

You can't have a circular reference, so unlike them all sharing an assembly, this enforces the direction of the dependencies from Assembly2 to Assembly1 only.

Related: I'd like a warning about circular namespace dependency

Community
  • 1
  • 1
weston
  • 54,145
  • 21
  • 145
  • 203