[ACCEPTED]-How to restrict access to nested class member to enclosing class?-access-levels

Accepted answer
Score: 88

Actually there is a complete and simple 5 solution to this problem that doesn't involve 4 modifying the client code or creating an 3 interface.

This solution is actually faster 2 than the interface-based solution for most 1 cases, and easier to code.

public class Journal
{
  private static Func<object, JournalEntry> _newJournalEntry;

  public class JournalEntry
  {
    static JournalEntry()
    {
      _newJournalEntry = value => new JournalEntry(value);
    }
    private JournalEntry(object value)
    {
      ...
Score: 58

If your class is not too complex, you could 21 either use an interface which is publicly 20 visible and make the actual implementing 19 class private, or you could make a protected 18 constructor for the JornalEntry class and have a private 17 class JornalEntryInstance derived from JornalEntry with a public constructor 16 which is actually instantiated by your Journal.

public class Journal
{
    public class JournalEntry
    {
        protected JournalEntry(object value)
        {
            this.Timestamp = DateTime.Now;
            this.Value = value;
        }

        public DateTime Timestamp { get; private set; }
        public object Value { get; private set; }
    }

    private class JournalEntryInstance: JournalEntry
    { 
        public JournalEntryInstance(object value): base(value)
        { }
    }
    JournalEntry CreateEntry(object value)
    {
        return new JournalEntryInstance(value);
    }
}

If 15 your actual class is too complex to do 14 either of that and you can get away with 13 the constructor being not completely invisible, you 12 can make the constructor internal so it 11 is only visible in the assembly.

If that 10 too is infeasible, you can always make the 9 constructor private and use reflection to 8 call it from your journal class:

typeof(object).GetConstructor(new Type[] { }).Invoke(new Object[] { value });

Now that 7 I think about it, another possibility would 6 use a private delegate in the containing 5 class which is set from the inner class

public class Journal
{
    private static Func<object, JournalEntry> EntryFactory;
    public class JournalEntry
    {
        internal static void Initialize()
        {
            Journal.EntryFactory = CreateEntry;
        }
        private static JournalEntry CreateEntry(object value)
        {
            return new JournalEntry(value);
        }
        private JournalEntry(object value)
        {
            this.Timestamp = DateTime.Now;
            this.Value = value;
        }

        public DateTime Timestamp { get; private set; }
        public object Value { get; private set; }
    }

    static Journal()
    {
        JournalEntry.Initialize();
    }
        
    static JournalEntry CreateEntry(object value)
    {
        return EntryFactory(value);
    }
}

This 4 should give you your desired visibility 3 levels without needing to resort on slow 2 reflection or introducing additional classes 1 / interfaces

Score: 29

Make JournalEntry a private nested type. Any public members will be visible 3 only to the enclosing type.

public class Journal
{
    private class JournalEntry
    {
    }
}

If you need to 2 make JournalEntry objects available to other classes, expose 1 them via a public interface:

public interface IJournalEntry
{
}

public class Journal
{
    public IEnumerable<IJournalEntry> Entries
    {
        get { ... }
    }

    private class JournalEntry : IJournalEntry
    {
    }
}
Score: 13

A simpler approach is to just use an internal constructor, but 7 make the caller prove who they are by supplying 6 a reference that only the legitimate caller could know (we don't need 5 to be concerned about non-public reflection, because 4 if the caller has access to non-public reflection 3 then we've already lost the fight - they 2 can access a private constructor directly); for 1 example:

class Outer {
    // don't pass this reference outside of Outer
    private static readonly object token = new object();

    public sealed class Inner {
        // .ctor demands proof of who the caller is
        internal Inner(object token) {
            if (token != Outer.token) {
                throw new InvalidOperationException(
                    "Seriously, don't do that! Or I'll tell!");
            }
            // ...
        } 
    }

    // the outer-class is allowed to create instances...
    private static Inner Create() {
        return new Inner(token);
    }
}
Score: 3

In this case you could either:

  1. Make the constructor internal - this stops those outside this assembly creating new instances or...
  2. Refactor the JournalEntry class to use a public interface and make the actual JournalEntry class private or internal. The interface can then be exposed for collections while the actual implementation is hidden.

I mentioned 6 internal as a valid modifier above however 5 depending on your requirements, private 4 may be the better suited alternative.

Edit: Sorry 3 I mentioned private constructor but you've 2 already dealt with this point in your question. My 1 apologies for not reading it correctly!

Score: 0

For generic nested class =)

I know this is an old question and it has 22 already an accepted answer, nevertheless 21 for those google swimmers who may have a 20 similar scenario to mine this answer may 19 provide some help.

I came across this question 18 for I needed to implement the same feature 17 as the OP. For my first scenario this and this answers 16 worked just fine. Nevertheless I needed 15 also to expose a nested generic class. The 14 problem is that you can not expose a delegate 13 type field (the factory field) with opened 12 generic parameters without making your own 11 class generic, but obviously this is not 10 what we want, so, here is my solution for 9 such scenario:

public class Foo
{
    private static readonly Dictionary<Type, dynamic> _factories = new Dictionary<Type, dynamic>();

    private static void AddFactory<T>(Func<Boo<T>> factory)
        => _factories[typeof(T)] = factory;

    public void TestMeDude<T>()
    {
        if (!_factories.TryGetValue(typeof(T), out var factory))
        {
            Console.WriteLine("Creating factory");
            RuntimeHelpers.RunClassConstructor(typeof(Boo<T>).TypeHandle);
            factory = _factories[typeof(T)];
        }
        else
        {
            Console.WriteLine("Factory previously created");
        }

        var boo = (Boo<T>)factory();
        boo.ToBeSure();
    }

    public class Boo<T>
    {
        static Boo() => AddFactory(() => new Boo<T>());

        private Boo() { }

        public void ToBeSure() => Console.WriteLine(typeof(T).Name);
    }
}

We have Boo as our internal nested 8 class with a private constructor and we 7 mantain on our parent class a dictionary 6 with these generic factories taking advantage 5 of dynamic. So, each time TestMeDude is called, Foo searches 4 for whether the factory for T has already 3 been created, if not it creates it calling 2 nested class' static constructor.

Testing:

private static void Main()
{
    var foo = new Foo();

    foo.TestMeDude<string>();
    foo.TestMeDude<int>();
    foo.TestMeDude<Foo>();

    foo.TestMeDude<string>();

    Console.ReadLine();
}

The 1 output is:

enter image description here

Score: 0

The solution Grizzly suggested does make 14 it a bit hard to create the nested class 13 somewhere else but not impossible,like Tim 12 Pohlmann wrote someone can still inherit 11 it and use the inheriting class ctor.

I'm 10 taking advantage of the fact that nested 9 class can access the container private properties, so 8 the container asks nicely and the nested 7 class gives access to the ctor.

 public class AllowedToEmailFunc
{
    private static Func<long, EmailPermit> CreatePermit;

    public class EmailPermit
    {
        public static void AllowIssuingPermits()
        {
            IssuegPermit = (long userId) =>
            {
                return new EmailPermit(userId);
            };
        }

        public readonly long UserId;

        private EmailPermit(long userId) 
        {
            UserId = userId;
        }
    }

    static AllowedToEmailFunc()
    {
        EmailPermit.AllowIssuingPermits();
    }

    public static bool AllowedToEmail(UserAndConf user)
    {
        var canEmail = true; /// code checking if we can email the user
        if (canEmail)
        {
            return IssuegPermit(user.UserId);
        }
        else
        {
            return null
        }

    }
}

This solution 6 is not something I would do on a regular 5 day on the job, not because it will lead 4 to problems in other places but because 3 it's unconventional (I've never seen it 2 before) so it might cause other developers 1 pain .

More Related questions