Is there a way to limit the instantiation of the nested class in C#? I want to prevent nested class being instantiated from any other class except the nesting class, but to allo
In short, no, you cannot do that. There is an accessibity modifier "public" which means "accessible by anything inside me or outside me" and there is an accessibility modifier "private" which means "accessible by anything inside me". There is no modifier which means "accessible to the thing immediately outside me but not to anything outside it", which is what you would need to mark the constructor as. That's simply not a concept that the designers of the type system thought would be useful.
Can you describe why you want this crazy kind of accessibility? Perhaps there is a better way to get what you want.
public class Outer
{
public class Nested
{
readonly Outer Outer;
public Nested(Outer outer /* , parameters */)
{
Outer = outer;
// implementation
}
// implementation
}
public Nested GetNested(/* parameters */) => new Nested(this /* , parameters */);
}
Note that you can access private members of Outer from Nested.
For the answer proposed by Joshua Smith I found it necessary to force the static constructor of FriendClass to run, achieved by calling an empty static Initalize() method on FriendClass from the static constructor of ParentClass.
Usually I create an interface for the functionality you want to expose to other classes, then make the nested class private and implement that interface. This way the nested class definition can stay hidden:
public class Outer
{
private class Nested : IFace
{
public Nested(...)
{
}
//interface member implementations...
}
public IFace GetNested()
{
return new Nested();
}
}
Since there is nothing in C# syntax you'll have to implement something like "a contract" between them. You can take advantage of the fact that nested class can access private fields of its parent:
public class ParentClass
{
private static Func<FriendClass> _friendContract;
public class FriendClass
{
static FriendClass()
{
_friendContract= () => new FriendClass();
}
private FriendClass() { }
}
///Usage
public FriendClass MethodUse()
{
var fInstance = _friendContract();
//fInstance.DoSomething();
return fInstance;
}
}
Of course you can adjust the contract to handle different parameters
private static Func<Arg1,Arg2,FriendClass> _friendContract;
If you need to meet one of the following requirements:
I found a solution similar to the one posted by ak99372, but without using a static initializer:
public class Outer
{
private interface IPrivateFactory<T>
{
T CreateInstance();
}
public sealed class Nested
{
private Nested() {
// private constructor, accessible only to the class Factory.
}
public class Factory : IPrivateFactory<Nested>
{
Nested IPrivateFactory<Nested>.CreateInstance() { return new Nested(); }
}
}
public Nested GetNested() {
// We couldn't write these lines outside of the `Outer` class.
IPrivateFactory<Nested> factory = new Nested.Factory();
return factory.CreateInstance();
}
}
The idea is that the Nested
class's constructor is accessible only to the Factory
class, which is nested one level deeper. The Factory
class explicitly implements the method CreateInstance
from the private interface IPrivateFactory
, so that only those who can see IPrivateFactory
can call CreateInstance
and get a new instance of Nested
.
Code outside the Outer
class can't freely create instances of Nested
without asking Outer.GetNested()
, because
Outer.Nested
's constructor is privated, so they can't call it directlyOuter.Nested.Factory
can be instantiated, but can't be cast to IPrivateFactory
, so its CreateInstance()
method can't be called.Note that I wouldn't recommend using that pattern heavily in production code, but it's a trick I find useful to have up my sleeve on rare occasions.