Chapter 8
Nested Classes
Nested classes are classes
created within existing classes.
a.cs
public class zzz
{
class yyy
{
}
public static void Main()
{
}
}
A simple example is shown above
where class yyy is created within class zzz.
a.cs
public class zzz
{
public static void Main()
{
xxx x = new xxx();
}
}
class yyy
{
class xxx
{
}
}
Compiler Error
a.cs(5,1): error CS0246: The type or namespace name 'xxx'
could not be found (are you missing a using directive or an assembly
reference?)
We are not allowed to use the
class xxx directly as it exists inside yyy and has no permanent existence at
all by itself. We cannot even define an object that looks like xxx.
a.cs
public class zzz
{
public static void Main()
{
yyy.xxx a = new yyy.xxx();
}
}
public class yyy
{
public xxx abc()
{
return new xxx();
}
public class xxx
{
}
}
The actual name of class xxx is
yyy.xxx as it is nested within the class yyy.
a.cs
public class zzz
{
public static void Main()
{
yyy.xxx a = new yyy.xxx();
System.Console.WriteLine(a.i);
}
}
public class yyy
{
public xxx abc()
{
return new xxx();
}
public class xxx
{
public static int i = 10;
}
}
Compiler Error
a.cs(7,26): error CS0176: Static member 'yyy.xxx.i' cannot be
accessed with an instance reference; use typename instead
The member i is static, hence we
need the name of the class and not name of object.
a.cs
public class zzz {
public static void Main() {
yyy.xxx a = new yyy.xxx();
System.Console.WriteLine(yyy.xxx.i);
}
}
public class yyy
{
public xxx abc()
{
return new xxx();
}
public class xxx
{
public static int i = 10;
}
}
Output
10
Static members work the same way
everywhere. No instance name required, only the name of class or classes.
a.cs
public class zzz
{
public static void Main()
{
yyy.xxx a = new yyy.xxx();
System.Console.WriteLine(a.j);
}
}
public class yyy
{
public int j = 2;
public xxx abc()
{
return new xxx();
}
public class xxx
{
public int i = 100;
}
}
Compiler Error
a.cs(7,26): error CS0117: 'yyy.xxx' does not contain a
definition for 'j'
The member j is in the class yyy,
not in xxx and hence the above error.
a.cs
public class zzz
{
public static void Main()
{
yyy.xxx a = new yyy.xxx();
System.Console.WriteLine(a.pqr());
}
}
public class yyy
{
public int j = 2;
public xxx abc()
{
return new xxx();
}
public class xxx
{
public int i = 100;
public int pqr()
{
return j;
}
}
}
Compiler Error
a.cs(22,8): error CS0038: Cannot access a non-static member of
outer type 'yyy' via nested type 'yyy.xxx'
The nested class xxx cannot
access the member j in class yyy as it is non-static. The fields of the
containing class are not automatically available to the nested class.
a.cs
public class zzz
{
public static void Main()
{
yyy.xxx a = new yyy.xxx();
System.Console.WriteLine(a.pqr());
}
}
public class yyy
{
public static int j = 2;
public xxx abc()
{
return new xxx();
}
public class xxx
{
public int i = 100;
public int pqr()
{
return yyy.j;
}
}
}
Output
2
The nested class xxx can access
static members of the class by simply doing what everyone else does, that is
preface the member with the name of the class.
a.cs
public class zzz {
public static void Main() {
yyy.xxx a = new yyy.xxx();
System.Console.WriteLine(a.pqr());
}
}
public class yyy
{
public int j = 2;
public xxx abc()
{
return new xxx();
}
public class xxx
{
public int i = 100;
public int pqr()
{
yyy h = new yyy();
return h.j;
}
}
}
Output
2
The non-static members can be
accessed as normal but we have to create an object that looks like yyy.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy();
}
}
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy");
}
public class xxx
{
public xxx()
{
System.Console.WriteLine("xxx");
}
}
}
Output
yyy
Creating an object that looks
like yyy does not create one that looks like the nested class xxx as the
constructor of class xxx does not get called at all.
a.cs
public class zzz {
public static void Main()
{
yyy.abc();
}
}
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy");
}
public static void abc()
{
xxx x = new xxx();
}
public class xxx
{
public xxx()
{
System.Console.WriteLine("xxx");
}
}
}
Output
xxx
The nested class is independent
of the containing class it resides in. The static function abc creates an
object that looks like xxx but the constructor of the class yyy is not executed.
a.cs
class zzz {
public class yyy
{
public static int v = 9;
}
}
class xxx : zzz
{
public static void Main()
{
zzz a = new zzz();
System.Console.WriteLine(a.yyy.v);
}
}
Compiler Error
a.cs(12,28): error CS0572: 'yyy': cannot reference a type
through an expression; try 'zzz.yyy' instead
The compiler comes back with the
right answer. As the member v is static, we have no choice but to use the name
of the class zzz and then the name of the inner class.
a.cs
class zzz
{
public class yyy
{
public static int v;
}
}
class xxx : zzz
{
public static void Main()
{
xxx.yyy.v = 5;
}
}
The compiler gives no error
messages. We are allowed to access a static member as shown in the program
above.
a.cs
class zzz
{
static void abc(int i)
{
}
static void abc(string s)
{
}
class yyy
{
void pqr()
{
abc(1);
abc("Hello");
}
static void abc(long l)
{
}
}
}
Compiler Error
a.cs(14,1): error CS1502: The best overloaded method match for
'zzz.yyy.abc(long)' has some invalid arguments
a.cs(14,5): error CS1503: Argument '1': cannot convert from
'string' to 'long'
The class zzz has two static
functions abc that accepts an int and a string. The nested class yyy creates
one more abc that accepts a long. The problem in this is that the two abc's in
class yyy get hidden. The compiler can convert a number one into a long, but
cannot convert the string into a long. Remove the abc from class yyy to see the
error disappear.
a.cs
class zzz {
class yyy : zzz {
public static void Main() {
}
}
}
The above example does not give
us a circular reference as the class yyy is derived from class zzz and it is
also a nested class within zzz. A circular reference occurs only if the class
zzz in turn is derived from class yyy directly or indirectly. Remember no one
likes circular references. A class is not dependent upon the classes it nests
in.
a.cs
public class zzz {
private static int i4 = 0;
public class yyy
{
public static int i1= 2;
internal static int i2 = 1;
private static int i3 = 0;
}
public class xxx
{
public static void Main()
{
zzz.yyy.i1= 1;
zzz.yyy.i2= 2;
zzz.yyy.i3= 3;
}
}
}
Compiler Error
a.cs(15,1): error CS0122: 'zzz.yyy.i3' is inaccessible due to
its protection level
The same rules binding access
modifiers apply to nested classes. The field i1 can be used everywhere. The
field i2 being internal can be used only in the current project and finally i3
being private as i4 is used only in class yyy and the containing class zzz.
a.cs
public class zzz
{
private static int i4 = 0;
private class yyy
{
public static int i1= 2;
internal static int i2 = 1;
private static int i3 = 0;
}
public class xxx
{
public static void Main()
{
zzz.yyy.i1= 1;
zzz.yyy.i2= 2;
zzz.yyy.i3= 3;
}
}
}
Compiler Error
a.cs(16,1): error CS0122: 'zzz.yyy.i3' is inaccessible due to
its protection level
Same explanation as above. Only
difference the nested class yyy is now private and not public but nothing
changes.
a.cs
namespace mmm
{
public class zzz
{
private class xxx
{
public static int i1 = 0;
internal static int i2 = 0;
private static int i3 = 0;
}
}
public class yyy
{
public static void Main()
{
zzz.xxx.i1= 1; // zzz
zzz.xxx.i2= 2; // zzz
zzz.xxx.i3= 3; // xxx
}
}
}
Compiler Error
a.cs(16,1): error CS0122: 'mmm.zzz.xxx' is inaccessible due to
its protection level
a.cs(17,1): error CS0122: 'mmm.zzz.xxx' is inaccessible due to
its protection level
a.cs(18,1): error CS0122: 'mmm.zzz.xxx' is inaccessible due to
its protection level
We have placed everything in a namespace. Now i1 and i2 and i3 are not accessible in class yyy. i1 and i2 are accessible in class zzz and i3 only in class xxx. The explanation has been given earlier.