C#外部类、内部类(嵌套类)之间的成员访问特点
- static成员与非static成员的访问:无论是外部类访问内部类的静态成员(变量和函数等),还是内部类访问外部类的静态成员,都不能用实例访问,必须用类本身访问;相应地,访问对方的非静态成员,则必须用实例访问。这与两个普通类之间的相互访问对方的static or non-static成员的方法是一致的。
- 关于访问限制:内部类可以访问外部类的任何访问级别的成员(public, internal, protected, private);而外部类只能访问内部类的public 或者internal级别的成员,不能访问内部类protected和private级别的成员。
- 关于调用方法:外部类调用内部类静态成员时,必须用“类名.成员名”的格式。内部类调用外部类静态成员时,如果内部类没有该外部类成员的同名成员,可以直接用“成员名”访问(也可以用“外部类.成员名”格式访问);如果内部类中定义了与外部类成员同名的静态成员,则内部类中方位外部类静态成员时,需要用"类名.成员名"的方式。
- 关于外部类的外部(其它类)访问内部类,这与访问一个普通类的方法相同,访问限制也相同,所不过类名是“外部类.内部类”。
下面以一个实例来说明:
Class1.cs
using System;
namespace ConsoleAppForTest001
{
public class OutSide
{
public int OS_num01;
private int OS_num02;
public static int OS_S_num01;
private static int OS_S_num02;
public int OS_Num02
{
get
{
return OS_num02;
}
set
{
OS_num02 = value;
}
}
public static int OS_S_Num02
{
get
{
return OS_S_num02;
}
set
{
OS_S_num02 = value;
}
}
public void say()
{
Console.WriteLine("OS_num01:{0}", OS_num01);
Console.WriteLine("OS_num02:{0}", OS_num02);
Console.WriteLine("OS_S_num01:{0}", OS_S_num01);
Console.WriteLine("OS_S_num02:{0}", OS_S_num02);
}
public InSide Creat_IS(int IS_num01, int IS_num02, int IS_S_num01, int IS_S_num02)
{
InSide.IS_S_num01 = IS_S_num01;
//InSide.IS_S_num02 = IS_S_num02;不可访问,因为有保护级别
InSide.IS_S_Num02 = IS_S_num02;
//InSide.OS_num01 = OS_num01;对于外部类的非静态成员需要实例化
InSide is01 = new InSide();
is01.IS_num01 = IS_num01;
//is01.IS_num02 = IS_num02;不可访问,因为有保护级别
is01.IS_Num02 = IS_num02;
return is01;
}
public class InSide
{
public int IS_num01;
private int IS_num02;
public static int IS_S_num01;
private static int IS_S_num02;
public int IS_Num02
{
get
{
return IS_num02;
}
set
{
IS_num02 = value;
}
}
public static int IS_S_Num02
{
get
{
return IS_S_num02;
}
set
{
IS_S_num02 = value;
}
}
public OutSide Creat_OS(int OS_num01, int OS_num02,int OS_S_num01, int OS_S_num02)
{
OutSide.OS_S_num01 = OS_S_num01;
OutSide.OS_S_num02 = OS_S_num02;
//OutSide.OS_num01 = OS_num01;对于外部类的非静态成员需要实例化;
OutSide os = new OutSide();
os.OS_num01 = OS_num01;
os.OS_num02 = OS_num02;
return os;
}
public virtual void say()
{
Console.WriteLine("IS_num01:{0}", IS_num01);
Console.WriteLine("IS_num02:{0}", IS_num02);
Console.WriteLine("IS_S_num01:{0}", IS_S_num01);
Console.WriteLine("IS_S_num02:{0}", IS_S_num02);
}
}
public class InSideSon: OtherFather//内部类继承其他类
{
public int ISS_numf;
public override void say()
{
Console.WriteLine("ISS_numf:{0}", ISS_numf);
}
}
}
public class OtherFather
{
public int OT_numf;
public virtual void say()
{
Console.WriteLine("OT_numf:{0}", OT_numf);
}
}
public class OtherSideSon: OutSide.InSide
{
public int OSS_numf;
public override void say()
{
Console.WriteLine("OSS_numf:{0}", OSS_numf);
}
}
}
其中OutSide是外部类,OtherFather是一个其他类,用作OutSide中的内部类OutSide.InSideSon: OtherFather来继承,而OtherSideSon: OutSide.InSide则恰恰相反,他继承了OutSide中的内部类OutSide.InSide。在另外一个.cs文件中,写下主函数并测试运行:
Program.cs
using System;
using System.Reflection;
namespace ConsoleAppForTest001
{
class Program
{
public static void Main(string[] args)
{
//外部类访问内部类
OutSide os01 = new OutSide();
OutSide.InSide is01 =os01.Creat_IS(10, 11, 12, 13);
is01.say();
Console.WriteLine("----------");
//内部类访问外部类
OutSide os02 = is01.Creat_OS(20,21,22,23);
os02.say();
Console.WriteLine("----------");
//反射内部类
Type isT01 = Type.GetType("ConsoleAppForTest001.OutSide+InSide");
Type[] pt = new Type[0];
ConstructorInfo isT01_CI = isT01.GetConstructor(pt);
Object[] obt = new Object[0];
Object ob = isT01_CI.Invoke(obt);
OutSide.InSide is02 = ob as OutSide.InSide;
is02.say();
Console.ReadKey();
}
}
}
这里通过:外部类访问内部类;内部类访问外部类;反射内部类;三个例子,说明了内部类的运行原理,其中尤为注意的是反射用到的名称中含一个“+”号,而非点。
运行结果:
运行结果应证了开头所说。