Thursday, July 8, 2010

Nested Types in c#

Nested Types
1.0 What is nested Type?
A nested type is a type defined within the scope of another type, which is called the enclosing type.e.g

// enclosing type
public class OuterType {
private string name;

// nested type
public class InnerType {
public InnerType(OuterType outer){
// the name field is private, but it works just fine
Console.WriteLine(outer.name);
}
}
}

Here .class “OuterType” is enclosing type. While class “InnerType” is nested type.

1.1 Default Access Modifier:
Regardless of whether the outer types is a class or a struct, nested types default to private, but can be made public, protected internal, protected, internal, or private.

1.2 Who Has What Access?:
Nested types can access private and protected members of the containing type, including any inherited private or protected members.

following c# console application deals extensively wrt access

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
/*InnerType class being public one can instantiate it as*/
OuterType.InnerType InnerTypeMainObj = new OuterType.InnerType();

/*PrivateInnerType class being private one can't instantiate it as*/
//OuterType.PrivateInnerType PrivateInnerTypeMainObj = new OuterType.PrivateInnerType();

/*ProtectedInnerType class being private one can't instantiate it as*/
//OuterType.ProtectedInnerType ProtectedInnerTypeMainObj = new OuterType.ProtectedInnerType();

/*InternalInnerType class being private one can instantiate it as*/
OuterType.InternalInnerType InternalInnerTypeMainObj = new OuterType.InternalInnerType();

/*ProtectedInternalInnerType class being private one can instantiate it as*/
OuterType.ProtectedInternalInnerType ProtectedInternalInnerTypeMainObj = new OuterType.ProtectedInternalInnerType();

}
}
public class BaseClass
{
/*non static base class field*/
private string privateBaseClassField = "privateBaseClassField";
protected string protectedBaseClassField = "protectedBaseClassField";
internal string internalBaseClassField = "internalBaseClassField";
protected internal string protectedInternalBaseClassField = "protectedInternalBaseClassField";
public string publicBaseClassField = "publicBaseClassField";

/*static base class field*/
private static string privateStaticBaseClassField = "privateStaticBaseClassField";
protected static string protectedStaticBaseClassField = "protectedStaticBaseClassField";
internal static string internalStaticBaseClassField = "internalStaticBaseClassField";
protected static internal string protectedInternalStaticBaseClassField = "protectedInternalStaticBaseClassField";
public static string publicStaticBaseClassField = "publicStaticBaseClassField";
}
//enclosing type
public class OuterType : BaseClass
{

/*accessing fields of inner class in outer class*/
public void accessInnerClass()
{
OuterType.InnerType InnerTypeObj = new OuterType.InnerType();
/*un-accessible being private & protected*/
//Console.WriteLine(InnerTypeObj.PrivateTypeNonStaicField);
//Console.WriteLine(InnerTypeObj.ProtectedTypeNonStaicField);

/*accessible*/
Console.WriteLine(InnerTypeObj.PublicNonStaicField);
Console.WriteLine(InnerTypeObj.InternaleNonStaicField);
Console.WriteLine(InnerTypeObj.ProtectedInternalNonStaicField);


}

/*non static fields*/
public string outerType_public_field = "outerType_public_field";
private string outerType_private_field = "outerType_private_field";
protected string outerType_protected_field = "outerType_protected_field";
internal string outerType_internal_field = "outerType_internal_field";
protected internal string outerType_protected_internal_field = "outerType_protected_internal_field";

/*static fields*/
public static string static_outerType_public_field = "static_outerType_public_field";
private static string static_outerType_private_field = "static_outerType_private_field";
protected static string static_outerType_protected_field = "static_outerType_protected_field";
internal static string static_outerType_internal_field = "static_outerType_internal_field";
protected internal static string static_outerType_protected_internal_field = "static_outerType_protected_internal_field";

/*public constructor*/
public OuterType()
{
Console.WriteLine("OuterType Public Constructor");
}
/*private constructor-5 parametres*/
private OuterType(string _priv, string _prot, string _inte, string _prot_inte, string _pub)
{
Console.WriteLine("OuterType private Constructor");
outerType_private_field = _priv;
outerType_protected_field = _prot;
outerType_internal_field = _inte;
outerType_protected_internal_field = _prot_inte;
outerType_public_field = _pub;
}

/***********protected constructor - 4 parametre***********
* you can not have two constructor with same
* signature except different access-modifier in a class
*/
protected OuterType(string _priv, string _prot, string _inte, string _prot_inte)
{
Console.WriteLine("OuterType protected Constructor");
outerType_private_field = _priv;
outerType_protected_field = _prot;
outerType_internal_field = _inte;
outerType_protected_internal_field = _prot_inte;
outerType_public_field = "public";
}

/*internal constructor*/
internal OuterType(string _prot, string _inte, string _prot_inte)
{
Console.WriteLine("OuterType internal Constructor");
outerType_private_field = "private";
outerType_protected_field = _prot;
outerType_internal_field = _inte;
outerType_protected_internal_field = _prot_inte;
outerType_public_field = "public";
}

/*internal constructor*/
protected internal OuterType(string _inte, string _prot_inte)
{
Console.WriteLine("OuterType internal Constructor");
outerType_private_field = "private";
outerType_protected_field = "protected";
outerType_internal_field = _inte;
outerType_protected_internal_field = _prot_inte;
outerType_public_field = "public";
}

// nested type
public class InnerType
{

/*non static field*/
private string PrivateTypeNonStaicField = "PrivateInnerTypeNonStaicField";
protected string ProtectedTypeNonStaicField = "PrivateInnerTypeNonStaicField";
public string PublicNonStaicField = "PublicInnerTypeNonStaicField";
internal string InternaleNonStaicField = "InternalInnerTypeNonStaicField";
protected internal string ProtectedInternalNonStaicField = "ProtectedInternalInnerTypeNonStaicField";

/*public constructor*/
public InnerType()
{
Console.WriteLine("InnerType Public Constructor");
}
/*private constructor*/
private InnerType(int i)
{
Console.WriteLine("InnerType private Constructor");
}
/*public method*/
public void publicInnerTypeMethod()
{

Console.WriteLine("publicInnerTypeMethod");
}
/*private method*/
private void privateInnerTypeMethod()
{
Console.WriteLine("privateInnerTypeMethod");
}

/*accessing OuterType members in inner-type*/
private void AccessOuterClassMember()
{
/******************static members***********************
* to access static members of outerclass we must not to create an
* instance (object) of outer class
***********************************************************/
Console.WriteLine(OuterType.static_outerType_internal_field);
Console.WriteLine(OuterType.static_outerType_private_field);
Console.WriteLine(OuterType.static_outerType_protected_field);
Console.WriteLine(OuterType.static_outerType_protected_internal_field);

/*************static member of base class of outerclass*************/

/*private static field of base class of outerclass are not accessible*/
//Console.WriteLine(OuterType.privateStaticBaseClassField);

/*protected field of base class of outerclass are accessible inside innerclass*/
Console.WriteLine(OuterType.protectedStaticBaseClassField);

/*public field of base class of outerclass are accessible inside innerclass*/
Console.WriteLine(OuterType.publicStaticBaseClassField);

/*protected internal field of base class of outerclass are accessible inside innerclass*/
Console.WriteLine(OuterType.protectedInternalStaticBaseClassField);


/*internal field of base class of outerclass are accessible inside innerclass*/
Console.WriteLine(OuterType.internalStaticBaseClassField);


/******************non-static members***********************
* to access non-static members of outerclass we need to create an
* instance (object) of outer class,static members of outer class are
* not accessible through an instance of class
***********************************************************/

/***********************using public constuctor**************
* Public constructor of outer class is accessible inside
* innerclass
*/
/*calling public constructor of outerType class inside innerType class*/
OuterType OuterTypeObjPublicConstructor = new OuterType();

OuterTypeObjPublicConstructor.outerType_internal_field = "INTERNAL";
OuterTypeObjPublicConstructor.outerType_private_field = "PRIVATE";
OuterTypeObjPublicConstructor.outerType_protected_field = "PROTECTED";
OuterTypeObjPublicConstructor.outerType_protected_internal_field = "PROTECTED INTERNAL";
OuterTypeObjPublicConstructor.outerType_public_field = "PUBLIC";

/**************accessing fields of base class of outer class*****************/
/*private field of base class of outerclass are not accessible inside innerclass*/
//Console.WriteLine(OuterTypeObjPublicConstructor.privateBaseClassField);

/*protected field of base class of outerclass are accessible inside innerclass*/
Console.WriteLine(OuterTypeObjPublicConstructor.protectedBaseClassField);

/*public field of base class of outerclass are accessible inside innerclass*/
Console.WriteLine(OuterTypeObjPublicConstructor.publicBaseClassField);

/*protected internal field of base class of outerclass are accessible inside innerclass*/
Console.WriteLine(OuterTypeObjPublicConstructor.protectedInternalBaseClassField);

/*all non-static field irrespective of access modifier are accessible
* through an instance of outerType class*/
Console.WriteLine(OuterTypeObjPublicConstructor.outerType_internal_field);
Console.WriteLine(OuterTypeObjPublicConstructor.outerType_private_field);
Console.WriteLine(OuterTypeObjPublicConstructor.outerType_protected_field);
Console.WriteLine(OuterTypeObjPublicConstructor.outerType_protected_internal_field);
Console.WriteLine(OuterTypeObjPublicConstructor.outerType_public_field);

/***********************using private constuctor*************
* private constructor of outer class is accessible inside
* innerclass
*/
/*calling private constructor of outerType class inside innerType class*/
OuterType OuterTypeObjPrivateConstructor = new OuterType("protected", "internal", "protected", "internal", "PUBLIC");

/*all non-static field irrespective of access modifier are accessible
* through an instance of outerType class*/
Console.WriteLine(OuterTypeObjPrivateConstructor.outerType_internal_field);
Console.WriteLine(OuterTypeObjPrivateConstructor.outerType_private_field);
Console.WriteLine(OuterTypeObjPrivateConstructor.outerType_protected_field);
Console.WriteLine(OuterTypeObjPrivateConstructor.outerType_protected_internal_field);
Console.WriteLine(OuterTypeObjPublicConstructor.outerType_public_field);

/***********************using protected constuctor*************
* private constructor of outer class is accessible inside
* innerclass
*/
/*calling protected constructor of outerType class inside innerType class*/
OuterType OuterTypeObjProtectedConstructor = new OuterType("private", "protected", "internal", "protected_internal");

/*all non-static field irrespective of access modifier are accessible
* through an instance of outerType class*/
Console.WriteLine(OuterTypeObjPrivateConstructor.outerType_internal_field);
Console.WriteLine(OuterTypeObjPrivateConstructor.outerType_private_field);
Console.WriteLine(OuterTypeObjPrivateConstructor.outerType_protected_field);
Console.WriteLine(OuterTypeObjPrivateConstructor.outerType_protected_internal_field);
Console.WriteLine(OuterTypeObjPublicConstructor.outerType_public_field);

/***********************using internal constuctor*************
* private constructor of outer class is accessible inside
* innerclass
*/
/*calling private constructor of outerType class inside innerType class*/
OuterType OuterTypeObjInternalConstructor = new OuterType("protected", "internal", "protected_internal");

/*all non-static field irrespective of access modifier are accessible
* through an instance of outerType class*/
Console.WriteLine(OuterTypeObjInternalConstructor.outerType_internal_field);
Console.WriteLine(OuterTypeObjInternalConstructor.outerType_private_field);
Console.WriteLine(OuterTypeObjInternalConstructor.outerType_protected_field);
Console.WriteLine(OuterTypeObjInternalConstructor.outerType_protected_internal_field);
Console.WriteLine(OuterTypeObjInternalConstructor.outerType_public_field);


/***********************using protected internal constuctor*************
* private constructor of outer class is accessible inside
* innerclass
*/
/*calling private constructor of outerType class inside innerType class*/
OuterType OuterTypeObjProtectedInternalConstructor = new OuterType("internal", "protected_internal");

/*all non-static field irrespective of access modifier are accessible
* through an instance of outerType class*/
Console.WriteLine(OuterTypeObjProtectedInternalConstructor.outerType_internal_field);
Console.WriteLine(OuterTypeObjProtectedInternalConstructor.outerType_private_field);
Console.WriteLine(OuterTypeObjProtectedInternalConstructor.outerType_protected_field);
Console.WriteLine(OuterTypeObjProtectedInternalConstructor.outerType_protected_internal_field);
Console.WriteLine(OuterTypeObjProtectedInternalConstructor.outerType_public_field);
}

public void AccessingSiblingNestedClass()
{
/*accessing non static members*/
PrivateInnerType PrivateInnerTypeObj = new PrivateInnerType();

/*private field of fellow inner type are not accessible*/
//Console.WriteLine(PrivateInnerTypeObj.PrivateInnerTypeNonStaicField);

/*protected field of fellow inner type are not accessible*/
//Console.WriteLine(PrivateInnerTypeObj.ProtectedInnerTypeNonStaicField);

/*public field of fellow inner type is accessible*/
Console.WriteLine(PrivateInnerTypeObj.PublicTypeNonStaicField);

/*internal field of fellow inner type is accessible*/
Console.WriteLine(PrivateInnerTypeObj.InternalTypeNonStaicField);

/*protected internal field of fellow inner type is accessible*/
Console.WriteLine(PrivateInnerTypeObj.ProtectedInternalTypeNonStaicField);

/***************************accessing static member****************/

/*private field of fellow inner type are not accessible*/
//Console.WriteLine(PrivateInnerType.PrivateStaticInnerTypeNonStaicField);

/*protected field of fellow inner type are not accessible*/
//Console.WriteLine(PrivateInnerType.ProtectedStaticInnerType);

/*public field of fellow inner type is accessible*/
Console.WriteLine(PrivateInnerType.PublicStaticType);

/*internal field of fellow inner type is accessible*/
Console.WriteLine(PrivateInnerType.InternalStaticType);

/*protected internal field of fellow inner type is accessible*/
Console.WriteLine(PrivateInnerType.ProtectedInternalStaticType);
}
}

//one more private nexted type
private class PrivateInnerType
{
/*non static field*/
private string PrivateInnerTypeNonStaicField="PrivateInnerTypeNonStaicField";
protected string ProtectedInnerTypeNonStaicField = "PrivateInnerTypeNonStaicField";
public string PublicTypeNonStaicField = "PublicInnerTypeNonStaicField";
internal string InternalTypeNonStaicField = "InternalInnerTypeNonStaicField";
protected internal string ProtectedInternalTypeNonStaicField = "ProtectedInternalInnerTypeNonStaicField";

/*static field*/
private static string PrivateStaticInnerTypeNonStaicField = "PrivateStaticInnerType";
protected static string ProtectedStaticInnerType = "PrivateStaticInnerType";
public static string PublicStaticType = "PublicStaticInnerType";
internal static string InternalStaticType = "InternalStaticInnerType";
protected static internal string ProtectedInternalStaticType = "ProtectedInternalStaticInnerType";
}


//one more private nexted type
protected class ProtectedInnerType
{
/*non static field*/
private string PrivateInnerTypeNonStaicField = "PrivateInnerTypeNonStaicField";
protected string ProtectedInnerTypeNonStaicField = "PrivateInnerTypeNonStaicField";
public string PublicTypeNonStaicField = "PublicInnerTypeNonStaicField";
internal string InternalTypeNonStaicField = "InternalInnerTypeNonStaicField";
protected internal string ProtectedInternalTypeNonStaicField = "ProtectedInternalInnerTypeNonStaicField";

/*static field*/
private static string PrivateStaticInnerTypeNonStaicField = "PrivateStaticInnerType";
protected static string ProtectedStaticInnerType = "PrivateStaticInnerType";
public static string PublicStaticType = "PublicStaticInnerType";
internal static string InternalStaticType = "InternalStaticInnerType";
protected static internal string ProtectedInternalStaticType = "ProtectedInternalStaticInnerType";
}

internal class InternalInnerType
{
/*non static field*/
private string PrivateInnerTypeNonStaicField = "PrivateInnerTypeNonStaicField";
protected string ProtectedInnerTypeNonStaicField = "PrivateInnerTypeNonStaicField";
public string PublicTypeNonStaicField = "PublicInnerTypeNonStaicField";
internal string InternalTypeNonStaicField = "InternalInnerTypeNonStaicField";
protected internal string ProtectedInternalTypeNonStaicField = "ProtectedInternalInnerTypeNonStaicField";

/*static field*/
private static string PrivateStaticInnerTypeNonStaicField = "PrivateStaticInnerType";
protected static string ProtectedStaticInnerType = "PrivateStaticInnerType";
public static string PublicStaticType = "PublicStaticInnerType";
internal static string InternalStaticType = "InternalStaticInnerType";
protected static internal string ProtectedInternalStaticType = "ProtectedInternalStaticInnerType";
}

protected internal class ProtectedInternalInnerType
{
/*non static field*/
private string PrivateInnerTypeNonStaicField = "PrivateInnerTypeNonStaicField";
protected string ProtectedInnerTypeNonStaicField = "PrivateInnerTypeNonStaicField";
public string PublicTypeNonStaicField = "PublicInnerTypeNonStaicField";
internal string InternalTypeNonStaicField = "InternalInnerTypeNonStaicField";
protected internal string ProtectedInternalTypeNonStaicField = "ProtectedInternalInnerTypeNonStaicField";

/*static field*/
private static string PrivateStaticInnerTypeNonStaicField = "PrivateStaticInnerType";
protected static string ProtectedStaticInnerType = "PrivateStaticInnerType";
public static string PublicStaticType = "PublicStaticInnerType";
internal static string InternalStaticType = "InternalStaticInnerType";
protected static internal string ProtectedInternalStaticType = "ProtectedInternalStaticInnerType";
}
}
}



The end user should rarely have to declare variables of a nested type and almost never explicitly instantiate nested types. For example, the enumerator of a collection can be a nested type of that collection. Enumerators are usually instantiated by their enclosing type and because many languages support the foreach statement, enumerator variables rarely have to be declared by the end user.

1.3 Do’s & Dont
DO use nested types when the relationship between the nested type and its outer type is such that member-accessibility semantics are desirable.
For example, the nested type needs to have access to private members of the outer-type.
public OrderCollection : IEnumerable<Order> {
Order[] data = ;

public IEnumerator<Order> GetEnumerator(){
return new OrderEnumerator(this);
}

// This nested type will have access to the data array
// of its outer type.
class OrderEnumerator : IEnumerator<Order> {
}
}

DO NOT use public nested types as a logical grouping construct; use namespaces for this.

DO NOT use nested types if the type is likely to be referenced outside of the containing type.
For example, an enum passed to a method defined on a class should not be defined as a nested type in the class.
DO NOT use nested types if they need to be instantiated by client code. If a type has a public constructor, it should probably not be nested.
If a type can be instantiated, it seems to indicate that the type has a place in the framework on its own (you can create it, work with it, and destroy it, without ever using the outer type), and thus should not be nested. Inner types should not be widely reused outside of the outer type without any relationship whatsoever to the outer type.
DO NOT define a nested type as a member of an interface. Many languages do not support such a construct.

No comments:

Post a Comment