Nested Classes

In addition to defining methods and fields within a class, it is possible to define a class within a class. Such classes are called nested classes. You use a nested class when the class makes little sense outside the context of its containing class.

Consider a class that handles the command-line options of a program. Such a class is generally unique to each program, so there is no reason to make a CommandLine class accessible from outside the class that contains Main().Listing 6.56 demonstrates such a nested class.

Listing 6.56: Defining a Nested Class
// CommandLine is nested within program
public class Program
{
    // Define a nested class for processing the command line
    private class CommandLine
    {
        public CommandLine(string[] arguments)
        {
            for (int argumentCounter = 0;
                argumentCounter < arguments.Length;
                argumentCounter++)
            {
                _ = argumentCounter switch
                {
                    0 => Action = arguments[0].ToLower(),
                    1 => Id = arguments[1],
                    2 => FirstName = arguments[2],
                    3 => LastName = arguments[3],
                    _ => throw new ArgumentException(
                        $"Unexpected argument " +
                        $"'{arguments[argumentCounter]}'")
                };
            }
        }
        public string? Action { get; }
        public string? Id { get; }
        public string? FirstName { get; }
        public string? LastName { get; }
    }
 
    public static void Main(string[] args)
    {
        CommandLine commandLine = new(args);
 
        // Error handling intentionally missing for elucidation.
 
        switch (commandLine.Action)
        {
            case "new":
                // Create a new employee
                // ...
                break;
            case "update":
                // Update an existing employee's data
                // ...
                break;
            case "delete":
                // Remove an existing employee's file
                // ...
                break;
            default:
                Console.WriteLine(
                    "Employee.exe " +
                    "new|update|delete " +
                    "<id> [firstname] [lastname]");
                break;
        }
    }
}

The nested class in this example is Program.CommandLine. As with all class members, no containing class identifier is needed from inside the containing class, so you can simply refer to it as CommandLine.

One unique characteristic of nested classes is the ability to specify private as an access modifier for the class itself. Because the purpose of this class is to parse the command line and place each argument into a separate field, Program.CommandLine is relevant only to the Program class in this application. The use of the private access modifier defines the intended accessibility of the class and prevents access from outside the class. You can do this only if the class is nested.

The this member within a nested class refers to an instance of the nested class, not the containing class. One way for a nested class to access an instance of the containing class is if the containing class instance is explicitly passed, such as via a constructor or a method parameter.

Another interesting characteristic of nested classes is that they can access any member on the containing class, including private members. The converse is not true, however: It is not possible for the containing class to access a private member of the nested class.

Nested classes are rare. They should not be defined if they are likely to be referenced outside the containing type. Furthermore, treat public nested classes with suspicion; they may be confusing and hard to discover.

Guidelines
AVOID publicly exposed nested types. The only exception is if the declaration of such a type is unlikely or pertains to an advanced customization scenario.
Language Contrast: Java—Inner Classes

Java includes not only the concept of a nested class but also the concept of an inner class. Inner classes correspond to objects that are associated with the containing class instance, rather than having just a syntactic relationship. In C#, you can achieve the same structure by including an instance field of a nested type within the outer class. A factory method or constructor can ensure a reference to the corresponding instance of the outer class is set within the inner class instance as well.

{{ snackbarMessage }}