Restricting instantiation of a nested class to its container

  • Thread starter Thread starter ex-neo-con
  • Start date Start date
E

ex-neo-con

I'd like to write code to make a nested class publicly available, but I
want to restrict its instantiation to instances of the containing
class. I know I could do such a thing using reflection, but that seems
a rather roundabout way of doing such a thing (not to mention the
processing overhead that doing so would incur).

Any suggestions?

ex-neo-con
 
When you say you want to "restrict its instantiation to instances of
the containing class," do you mean "I want only the containing class to
be able to instantiate one of these," or do you mean, "Whenever any
class asks to instantiate one of these I want to return an instance of
the containing class instead?"

If it's the former, then it's easy to get close: just declare the
constructor as "internal". Other classes within the same assembly will
still be able to instantiate it, but anything outside the assembly will
not. There is no "containing class only" scope, so you can't get things
exactly the way you want them.

If it's the latter (which is odd, by the way), a variation on the
Singleton pattern should get it for you.
 
It's the latter, and I did come up with a way to do it:

using System;

public class MyClass {

public abstract class MyNestedClass {
public void Foo(){
Console.WriteLine("This is an instance of MyNestedClass");
}
}

private class MyConcreteNestedClass : MyNestedClass {

}

public MyNestedClass GetNestedClassInstance(){
return new MyConcreteNestedClass();
}

public static void Main(){
MyClass c = new MyClass();
c.GetNestedClassInstance().Foo();
Console.ReadLine();
}
}

But you mention that what I'm doing is odd. I'm curious as to what
might be a better way of conceiving the problem.

ex-neo-con
 
Actually, that wouldn't necessarily work: any one who wants to derive
form MyNestedClass could instantiate such an object--though not
MyConcreteNestedClass.

ex-neo-con
 
I'm not sure why a version of Singleton would work. I mean, I'm not
really creating a singleton--although the creation mechanism might be
similar. Is that what you mean?

ex-neo-con
 
If you give MyNestedClass an internal constructor, rather than a
default public constructor, then at least no code outside your assembly
can instantiate it directly, and no class outside your assembly can
inherit from it.
 
What I meant by a variation on the Singleton pattern is that
GetNestedClassInstance could be a static method of MyNestedClass,
although it very much depends upon your constructor arguments (whether
you need information from an instance of MyClass in order to intantiate
a MyNestedClass).

I think I understand, now: you want to be able to create an instance of
MyNestedClass only via MyClass, but once you have it you want to be
able to call its methods, etc. I think you're almost there: just make
the MyNestedClass constructor internal. Then you don't even need
MyNestedConcreteClass.

I believe that this is how things like ListItemCollection work in the
..NET Framework. Look into that (and similar) classes: you can get it
back only as a result of the ListView.Items property. You can't
instantiate one on its own, but you can call its methods once you have
one in hand. If this is what you want then it's not odd: find out how
Microsoft set it up and do the same. :)
 
Hmmm. Doesn't the internal keyword only restrict access to (1) classes
in the same assembly and (2) derived classes in other assemblies?

Thanks for the tip on ListItemCollection. I knew that MS does that in
an umber of places, but I couldn't remember off the top of my head
where. Time to fire-up .NET Reflector!

ex-neo-con
 
the cleanest way I can think of is to make the nested class private but
expose all the properties and methods you want the outside to see through an
interface. that way the class instantiation can only be done by the parent
class.
 
Not quite. "internal" restricts access to only those classes in the
same assembly. You're thinking of "protected internal", which restricts
access as you described.
 

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

Back
Top