Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Private inner classes in C# - why aren't they used more often?

I am relatively new to C# and each time I begin to work on a C# project (I only worked on nearly mature projects in C#) I wonder why there are no inner classes?

Maybe I don't understand their goal. To me, inner classes -- at least private inner classes -- look a lot like "inner procedures" in Pascal / Modula-2 / Ada : they allow to break down a main class in smaller parts in order to ease the understanding.

Example : here is what is see most of the time :

public class ClassA
{
   public MethodA()
   {
      <some code>
      myObjectClassB.DoSomething(); // ClassB is only used by ClassA
      <some code>
   }
}

public class ClassB
{
   public DoSomething()
   {
   }
}

Since ClassB will be used (at least for a while) only by ClassA, my guess is that this code would be better expressed as follow :

   public class ClassA
   {
      public MethodA()
      {
         <some code>
         myObjectClassB.DoSomething(); // Class B is only usable by ClassA
         <some code>
      }

      private class ClassB
      {
         public DoSomething()
         {
         }
      }
   }

I would be glad to hear from you on this subject - Am I right?

like image 896
Sylvain Rodrigue Avatar asked Jan 17 '09 22:01

Sylvain Rodrigue


People also ask

What is a private inner class?

Unlike a class, an inner class can be private and once you declare an inner class private, it cannot be accessed from an object outside the class. Following is the program to create an inner class and access it. In the given example, we make the inner class private and access the class through a method.

Can nested classes be private?

Static nested classes do not have access to other members of the enclosing class. As a member of the OuterClass , a nested class can be declared private , public , protected , or package private.

Does inner class have access private variables?

So, yes; an object of type Outer::Inner can access the member variable var of an object of type Outer .


3 Answers

Nested classes (probably best to avoid the word "inner" as nested classes in C# are somewhat different to inner classes in Java) can indeed be very useful.

One pattern which hasn't been mentioned is the "better enum" pattern - which can be even more flexible than the one in Java:

public abstract class MyCleverEnum
{
    public static readonly MyCleverEnum First = new FirstCleverEnum();
    public static readonly MyCleverEnum Second = new SecondCleverEnum();

    // Can only be called by this type *and nested types*
    private MyCleverEnum()
    {
    }

    public abstract void SomeMethod();
    public abstract void AnotherMethod();

    private class FirstCleverEnum : MyCleverEnum
    {
        public override void SomeMethod()
        {
             // First-specific behaviour here
        }

        public override void AnotherMethod()
        {
             // First-specific behaviour here
        }
    }

    private class SecondCleverEnum : MyCleverEnum
    {
        public override void SomeMethod()
        {
             // Second-specific behaviour here
        }

        public override void AnotherMethod()
        {
             // Second-specific behaviour here
        }
    }
}

We could do with some language support to do some of this automatically - and there are lots of options I haven't shown here, like not actually using a nested class for all of the values, or using the same nested class for multiple values, but giving them different constructor parameters. But basically, the fact that the nested class can call the private constructor gives a lot of power.

like image 100
Jon Skeet Avatar answered Oct 24 '22 09:10

Jon Skeet


The Framework Design Guidelines has the best rules for using nested classes that I have found to date.

Here's a brief summary list:

  1. Do use nested types when the relationship between type and nested type is such the member-accessibility semantics are desired.

  2. Do NOT use public nested types as a logical group construct

  3. Avoid using publicly exposed nested types.

  4. Do NOT use nested types if the type is likely to be referenced outside of the containing type.

  5. Do NOT use nested types if they need to be instantiated by client code.

  6. Do NOT define a nested type as a member of an interface.

like image 31
matt_dev Avatar answered Oct 24 '22 08:10

matt_dev


You should limit the responsibilities of each class so that each one stays simple, testable and reusable. Private inner classes go against that. They contribute to the complexity of the outer class, they are not testable and they are not reusable.

like image 12
Wim Coenen Avatar answered Oct 24 '22 07:10

Wim Coenen