C#嵌套類 內部類


嵌套類

Nesting Classes

類都有成員,而類的成員是另一個用戶定義類型是完全可能的。比如,Button類可以有許多Location類型的成員,而Location類又包含許多Point類型的成員。Point也可以包含許多int類型的成員。

偶爾,被包含的類可以就是為其外層類服務而存在的,因此它不必向外界暴露。(說得簡單點兒, 被包含類只是一個輔助類。)可以在外層類的定義中定義輔助類。這種被包含的內部類我們稱之為嵌套類(nested class),而包含它的類我們直接稱為外層類(outer class)。

嵌套類的好處是可以對外層類的所有成員進行訪問。嵌套類的方法可以訪問外層類的私有成員。

提示:而且,嵌套類可以對其他所有類隱藏,即它是外層類的私有成員。

還要說明,公共的嵌套類可以在外層類的作用域內訪問。如果Outer是一個外層類,而Nested是(公共的)內部類,可以稱Nested為Outer.Nested,其中外層類就或多或少地成為一種名字空間或作用域了。

提示:Java程序員注意了:嵌套類略等價於Java的靜態內部類,但C#中不存在Java非靜態內部類的等價物。

示例5-5在Fraction中添加了嵌套類FractionArtist。該類的作用是在控制台畫出分數。本示例中繪制是用一對WriteLine()語句代替的。

示例5-5:使用嵌套類

#region Using directives

using System;

using System.Collections.Generic;

using System.Text;

示例5-5:使用嵌套類(續例)

#endregion

namespace NestedClasses

{

   public class Fraction

   {

      private int numerator;

      private int denominator;

      public Fraction( int numerator, int denominator )

      {

         this.numerator = numerator;

         this.denominator = denominator;

      }

      public override string ToString()

      {

         return String.Format( "{0}/{1}",

             numerator, denominator );

      }

      internal class FractionArtist

      {

         public void Draw( Fraction f )

         {

            Console.WriteLine( "Drawing the numerator: {0}",

               f.numerator );

            Console.WriteLine( "Drawing the denominator: {0}",

               f.denominator );

         }

      }

   }

   public class Tester

   {

      static void Main()

      {

         Fraction f1 = new Fraction( 3, 4 );

         Console.WriteLine( "f1: {0}", f1.ToString() );

         Fraction.FractionArtist fa = new Fraction.FractionArtist();

         fa.Draw( f1 );

      }

   }

}

嵌套類用黑體顯示。FractionArtist類只有一個成員:Draw()方法。更有趣的是,Draw()可以訪問私有數據成員f.numerator和f.denominator,如果不是嵌套類是根本不可能的。

注意在Main()中,要聲明此嵌套類的一個實例,必須指定外層類的類型名:

Fraction.FractionArtist fa = new Fraction.FractionArtist();

FractionArtist的作用域限於Fraction類中。

 出自:http://blog.csdn.net/mydriverc/archive/2008/03/01/2137884.aspx

 嵌套類(Nested Class)是在類中定義的類。以下把擁有內嵌類的類稱為外部類。根據《深入理解嵌套類和內部類》嵌套類分為靜態嵌套類和非靜態嵌套類,其中非靜態嵌套類 頁被稱為內部類。 嵌套類在UML中是composite的另外一種代碼表示形式,表示耦合度更高,並且與外部類更加緊密。
       一般類的 訪問修飾符可以定義為默認的internal 或者public,而內嵌類就有比較多的選擇,可以是為protected、internal、public以及默認的private。

內嵌類與外部類的訪問限制
      嵌套類可以訪問外部類的方法、屬性、字段而不管訪問修飾符的限制。如:

 public class A
    {
        private static int _AInt;
        private int _instanceInt;
        private static void AMethod()
        {
            Console.WriteLine(_AInt);
        }
        public void SayIt()
        {
            NestedA.Method(this);
        }
        /*嵌套類 定義*/
        private class NestedA
        {
            public static void Method(A a)
            {
                //靜態成員
                _AInt = 100;
                AMethod();
                //實例成員
                a._instanceInt = 10;
                a.SayIt();
            }
        }
    }
      但是外部類只能夠訪問修飾符為public、internal嵌套類的字段、方法、屬性。示例如下:

 public class A
    {
        public static void AMethod()
        {
            //成功
            NestedA.StaticMethod();
            //編譯報錯
            NestedA._Int = 100;
           
            NestedA ins=new NestedA();
            //成功
            ins.Method();
            //編譯報錯
            ins._instanceInt = 100;
        }
        /*嵌套類 定義*/
        private class NestedA
        {
            private static int _Int;
            private int _instanceInt;
            public static void StaticMethod() { }
            public void Method(){}
        }
    }
    嵌套類訪問外部類實例的方法、字段、屬性時候。一般在采取構造函數輸入外部類。如下:

  public class A
        {
            private int _a;
          
            /*嵌套類 定義*/
            private class NestedA
            {
                public NestedA(A a)
                {
                    a._a = 9;
                }             
            }
        }
 繼承
        繼承類,也就是繼承類外部類的類,只能使用父類中嵌套類的public或者internal(同一個程序集合)方法。但是繼承類可以再定義一個內嵌類並從繼承父類中嵌套類。如:

public class A
{
            /*嵌套類 定義*/
            protected class Nested
            {
                protected virtual void BaseNested_Method(){}
            }
}

 public class C : A
{
      /*內嵌類 定義*/
      protected class C_Nested:Nested
      {
                protected override void BaseNested_Method()
                {
                    //重寫部分
        }
       }
 }
      因為C中A中繼承,因此C_Nested可以繼承Nested類,從而獲取重寫父嵌套類的機會。但是Nested必須是可繼承類及可訪問的(非private 、sealed、static)。

         嵌套類可以隨意外部類的任何數據屬性,而外部類訪問嵌套類就只能遵守訪問修飾符。從這個角度看,嵌套類是外部類的補充,通過嵌套類可以獲取更好的封裝性,增加外部類的可維護性和可讀性。       

      從程序結構看,嵌套類在邏輯上更加接近使用類。可以更有效地表示類與類之間的緊密程度。為類管理提供除命名空間外的另一種方法。

懶加載

        嵌套類的靜態構造函數不會隨着外部類的觸發而初始化。因此可以有效地避免創建時候初始化時間,當需要使用內嵌類的時候,嵌套類才開始初始化才開始初始化。

public class Outside
{
    static Outside()
    {
        Console.WriteLine("Outside Inilizlized");
    }
    public void SayIt()
    {
        Nested.Run();
    }
    private class Nested
    {
        static Nested()
        {
            Console.WriteLine("Nested initilized");
        }

        public static void Run()
        {
            Console.WriteLine("Nested Run");
        }
    }
}
執行結果

 Outside o = new Outside();//打印"Outside Inilizlized"
 Console.ReadLine();
 o.SayIt();//首先打印"Nested initilized" 再打印 "Nested Run"
 Console.ReadLine();
      一般應用這個特性會在一些C#單例模式中找到,而這種模式可以被稱為Fully lazy singleton模式。下面是簡單的演示代碼(Singleton模式可以在這里有更加詳細的解釋):

public class Singleton
    {
        public static Singleton Instance
        {
            get
            {
                return Nested.instance;
            }
        }
        private class Nested
        {
            public readonly static Singleton instance=new Singleton();
        }
}
 反射

      反射內嵌類需要使用"+"而不是我們常使用的"." 。如A類在Assembly名稱為InsideClass中。

namespace InsideClass
{
    public class A
    {
         public class Nested
        {
            protected void BaseNested_Method()
            {
            }
        }
     }
}

執行

 //成功
object o1 = System.Activator.CreateInstance("InsideClass", "InsideClass.A+Nested");
 //失敗 拋出System.TypeLoadException 異常
object o2 = System.Activator.CreateInstance("InsideClass", "InsideClass.A.Nested");

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/mydriverc/archive/2008/03/01/2137884.aspx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM