亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

發布時間:2020-07-25 09:34:51 來源:網絡 閱讀:1882 作者:yisuowushinian 欄目:編程語言

目錄:

【C#小知識】C#中一些易混淆概念總結

【C#小知識】C#中一些易混淆概念總結(二)

---------------------------------------分割線----------------------------------------------

一,C#中結構

在C#中可以使用struct關鍵字來定義一個結構,級別與類是一致的,寫在命名空間下面。

1)結構中可以定義屬性,字段,方法和構造函數。示例代碼如下:

//定義結構
    struct Point
    {
                                                                                       
        //定義字段
        private int x;
        //封裝字段
        public int X
        {
            get { return x; }
            set { x = value; }
        }
                                                                                        
        //定義方法
        public void Result()
        {
                                                                                            
        }
        //定義構造函數
        public Point(int n)
        {
            this.x = n;
            //Console.WriteLine(n);
        }
    }


那么,聲明類與結構的區別有哪些呢?

無論如何,C#編譯器都會為結構生成無參數的構造函數;

當我們顯式的定義無參數的構造函數,編譯時會報錯,結果如下:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

編譯器告訴我們,結構不能包含顯式的無參數的構造函數

但是這樣編寫代碼時,編譯器卻不報錯,代碼如下:

//這里可以調用無參數的構造函數

Point p = new Point();            

Console.WriteLine(p.GetType());

運行結果如下:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

雖然結構不能顯式的聲明無參數的構造函數,但是程序員卻可以顯式的調用結構的無參數的構造函數,說明C#編譯器無論如何都會為結構生成無參數的構造函數。

②結構中的字段不能賦初始值;

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

③在結構的構造函數中必須要對結構體的每一個字段賦值;

當我們不聲明顯式的構造函數時,可以不對成員字段賦值,但是一旦聲明了構造函數,就要對所有的成員字段賦值

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

對所有的成員字段賦值,代碼如下:

     //定義構造函數

public Point(int n)        

{            

   this.x = n;            

   //Console.WriteLine(n);

}

④在構造函數中對屬性賦值不認為對字段賦值,屬性不一定去操作字段;

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

所以在構造函數中我們對字段賦初始值的時候,正確的代碼應該是

//定義構造函數
        public Point(int n)
        {
            //正確的可以對字段賦初始值
            this.x = n;
            //在構造函數中對屬性賦值,但是不一定操作字段
            this.X = n;
            //Console.WriteLine(n);
        }


2)結構體的數值類型問題

C#中的結構是值類型,它的對象和成員字段是分配在棧中的,如下圖:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

那么當我們寫了如下的代碼,內存中發生了什么呢?

//這里可以調用無參數的構造函數
          Point p = new Point();
          //為p的屬性賦值
          p.X = 100;
          //將p賦值給Point新的對象p1
          Point p1 = p;


Point p1=p發生了什么呢?情況如下:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

聲明結構體對象可以不使用“new”關鍵字如果不使用“new”關鍵字聲明結構體對象,因為沒有調用構造函數,這個時候結構體對象是沒有值的。而結構的構造函數必須為結構的所有字段賦值,所以通過"new"關鍵字創建結構體對象的時候,這個對象被構造函數初始化就有默認的初始值了。實例代碼如下

class Program
    {
        static void Main(string[] args)
        {
           //沒有辦法調用默認的構造函初始化
            Point p;
            Console.WriteLine(p);
            //會調用默認的構造函數對的Point對象初始化
            Point p1 = new Point();
            Console.WriteLine(p1);
            Console.ReadKey();
        }
    }
    //定義結構
    struct Point
    {
        //定義時賦初始值,編譯器會報錯
        private int x;
    }


編譯的時候會報錯:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


3)結構體不能使用自動屬性

在第一篇文章我寫自動屬性的時候,反編譯源代碼,知道自動屬性,會生成一個默認字段。而在結構的構造函數中需要對每一個字段賦值,但是編譯器不知道這個字段的名字。所以,沒有辦法使用自動屬性。


那么什么時候定義類,什么時候定義結構體呢?

首先我們都知道的是,棧的訪問速度相對于堆是比較快的。但是棧的空間相對于堆來說是比較小的。

①當我們要表示一個輕量級的對象,就可以定義結構體,提高訪問速度。

②根據傳值的影響來選擇,當要傳遞的引用就定義類,當要傳遞的是“拷貝”就定義結構體。

二,關于GC(.NET的垃圾回收)

1)分配在棧中的空間變量,一旦出了該變量的作用域就會被CLR立即回收;如下代碼:

//定義值類型的n當,程序出了main函數后n在棧中占用的空間就會被CLR立即回收
        static void Main(string[] args)
        {
            int n = 5;
            Console.WriteLine(n);
        }

2)分配在堆里面的對象,當沒有任何變量的引用時,這個對象就會被標記為垃圾對象,等待垃圾回收器的回收;

GC會定時清理堆空間中的垃圾對象,這個時間頻率是程序員無法控制的,是由CLR決定的。所以,當一個對象被標記為垃圾對象的時候,不一定會被立即回收。

3)析構函數

在回收垃圾對象的時候,析構函數被GC自動調用。主要是執行一些清理善后工作。

析構函數沒有訪問修飾符,不能有你參數,使用“~”來修飾。 如下面的代碼示例:

class Program
    {
        //定義值類型的n當,程序出了main函數后n在棧中占用的空間就會被CLR立即回收
        static void Main(string[] args)
        {
            int n = 5;
            OperateFile operate = new OperateFile();
            operate.FileWrite();
            //執行完寫操作后,會調用該類的析構函數,釋放對文件對象的控制
            //Console.WriteLine(n);
        }
    }
    //定義操作硬盤上文件上的類
    class OperateFile
    {
        //定義寫文件的方法
        public void FileWrite()
        { }
        //定義調用該類結束后,所要執行的動作
        ~OperateFile()
        {
        //釋放對操作文件對象的控制
        }
    }


三,靜態成員和實例成員的區別:

靜態成員是需要通過static關鍵字來修飾的,而實例成員不用static關鍵字修飾。他們區別如下代碼:

class Program
    {
        static void Main(string[] args)
        {
            //靜態成員屬于類,可以直接通過“類名.靜態成員”的方式訪問
            Person.Run();
            //實例成員屬于對象,需要通過“對象名.實例成員”來訪問
            Person p = new Person();
            p.Sing();
        }
    }
    class Person
    {
        //靜態成員變量
        private static int nAge;
        //實例成員變量
        private string strName;
        public static void Run()
        {
            Console.WriteLine("我會奔跑!");
        }
        public void Sing()
        {
            Console.WriteLine("我會唱歌");
        }
    }

當類第一次被加載的時候(就是該類第一次被加載到內存當中),該類下面的所有靜態的成員都會被加載。實例成員有多少對象,就會創建多少對象。

而靜態成員只被加載到靜態存儲區,只被創建一次,且直到程序退出時才會被釋放。

看下面的代碼:

class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
            Person p1 = new Person();
            Person p2 = new Person();
        }
    }
                                      
    class Person
    {
        //靜態成員變量
        private static int nAge;
        //實例成員變量
        private string strName;
        public static void Run()
        {
            Console.WriteLine("我會奔跑!");
        }
        public void Sing()
        {
            Console.WriteLine("我會唱歌");
        }
    }

那么在內存中發生了什么呢?如下圖:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


由上面顯然可知,定義靜態的成員是可以影響程序的執行效率的。那么什么時候定義靜態的成員變量呢?

①變量需要被共享的時候②方法需要被反復的調用的時候

2)在靜態方法中不能直接調用實例成員。

當類第一次被加載的時候,靜態成員已經被加載到靜態存儲區,此時類的對象還有可能能沒有創建,所以靜態方法中不能調用類成員字段。實例代碼如下:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


this和base關鍵字都不能在靜態方法中使用。

②可以創建類的對象指明對象的成員在靜態方法中操作,代碼如下:

public static void Run()
       {
           Person p = new Person();
           p.strName = "強子";
           Console.WriteLine("我會奔跑!");
       }

③在實例成員中肯定可以調用靜態方法,因為這個時候靜態成員肯定存在,代碼如下:

public static void Run()
        {
            Person p = new Person();
            p.strName = "強子";
            Console.WriteLine("我會奔跑!");
        }
        public void Sing()
        {
            //實例方法被調用的時候,對象實例一定會被創建,所以可以在實例方法中訪問實例的字段
            this.strName = "子強";
            strName = "子強";
            //調用靜態成員
            Run();
            Console.WriteLine("我會唱歌");
        }

靜態成員和實例成員的對比:

①生命周期不一樣

靜態成員只有在程序結束時才會釋放,而實例成員沒有對象引用時就會釋放

②內存中存儲的位置不一樣

靜態成員存放在靜態存儲區,實例成員在托管堆中。


四,靜態類

①靜態類被static關鍵字修飾

//定義兩個靜態類

staticclass Person    { }  

internalstaticclass Cat    { }


②靜態類中只能生命靜態的成員變量,否則會報錯(因為訪問該實例成員的時候,類的對象可能還沒有被創建

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類

③靜態類中不能有實例的構造函數(如果有實例的構造函數,則該靜態類能被實例化,都是靜態成員,沒有實例成員被調用

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


正確的聲明方法:

static class Person
    {
        //private int nAge;
        private static string strName;
        static Person()
        {
        }
    }


④靜態類不能被繼承,反編譯剛才的兩個類,結果如下:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


會發現靜態類的本質是一個抽象密封類,所以不能被繼承和實例化。所以,靜態類的構造函數,不能有訪問修飾符


2)那么什么時候聲明靜態類呢?

如果這個類下面的所有成員的都需要被共享,可以把這個類聲明為靜態類。

且在一般對象中不能聲明靜態類型的變量(訪問該靜態變量時,可能該對象還沒有被創建)。

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


3)靜態類的構造函數

靜態類可以有靜態的構造函數(且所有類都可以有靜態的構造函數),如下代碼:

class Program
    {
        static void Main(string[] args)
        {
            Cat c;
            Cat c1 = new Cat();
            Console.ReadKey();
        }
    }
    class Cat
    {
        private int n;
        public string strName;
        //實例構造函數
        public Cat()
        {
            Console.WriteLine("看誰先執行2");
        }
        //靜態構造函數
        static Cat()
        {
            Console.WriteLine("看誰先執行1");
        }
    }

執行結果如下:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


由此我們可以知道,靜態的構造函數會先于實例構造函數執行

//不執行靜態構造函數

Cat c;

當我們在Main()函數中添加如下的代碼是:

static void Main(string[] args)
        {
            //不執行靜態構造函數
            Cat c;
            Cat c1 = new Cat();
            Cat c2 = new Cat();
            Console.ReadKey();
        }

運行結果如下:

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


說明靜態的構造函數只執行了一次。

---------------------------------------------分割線-----------------------------------------------


好吧這次的分享風到此結束。希望對大家對理解C#基礎概念知識能有所幫助。


如果您覺得不錯,點擊右下角贊一下吧!您的支持,是我寫作的動力!

畢業實習交流群:221376964。你也可以關注我的新浪微博進行交流。

C#中一些易混淆概念總結(三)--------結構,GC回收,靜態成員,靜態類


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

故城县| 绥宁县| 永新县| 秦安县| 瓮安县| 永城市| 绍兴市| 互助| 嘉黎县| 孝感市| 大名县| 衡阳市| 杂多县| 岳阳市| 屯留县| 衢州市| 当涂县| 临桂县| 册亨县| 同心县| 勐海县| 旬邑县| 金阳县| 沙洋县| 铅山县| 黄骅市| 象山县| 乌拉特后旗| 加查县| 托克托县| 富平县| 贵定县| 金湖县| 和平区| 渭源县| 开平市| 大厂| 新安县| 尼勒克县| 大新县| 崇州市|