關於C#中靜態的一點認識

来源:https://www.cnblogs.com/green-jcx/archive/2020/06/26/13194853.html
-Advertisement-
Play Games

1.靜態直觀的特點 靜態成員最顯著的一個特點就是它的作用域是全局的。只要在調用處引入了對應的命名空間,那麼我們可以在代碼任何地方都可以直接使用。凡是具有全局特征的東西我們就可以考慮使用靜態。在實際的開發中,靜態欄位我們常用實現數據的共用,修飾為靜態的方法當做常用的工具方法來使用。 2.命名上的思考 ...


1.靜態直觀的特點

  靜態成員最顯著的一個特點就是它的作用域是全局的。只要在調用處引入了對應的命名空間,那麼我們可以在代碼任何地方都可以直接使用。凡是具有全局特征的東西我們就可以考慮使用靜態。在實際的開發中,靜態欄位我們常用實現數據的共用,修飾為靜態的方法當做常用的工具方法來使用。

 

2.命名上的思考

  靜態從名稱的對立面上可以想到一個詞叫動態,這裡所說的動態可以隱喻為實例成員。實例成員之所以可以形容為動態因為在記憶體中它的創建和釋放資源是根據實例化對象或GC(垃圾回收)不斷變化的。而靜態成員在記憶體中很少會發生變化,靜態成員的創建是在第一次訪問對應的類型時進行的創建,資源釋放是在應用程式結束的時候。

 

3.靜態和實例(非靜態)的對比

靜態

實例(非靜態)

需要static關鍵字

不需要static關鍵字

無法實例化只能使用類名調用

必須實例化對象後才能調用

在靜態方法中,可以訪問靜態成員

在實例方法中,可以訪問靜態成員

在靜態方法中不可以直接訪問實例成員,如需訪問需要創建對象

在實例方法中,可以直接訪問實例成員

調用前初始化(在創建第一個實例或引用任何靜態成員之前)

實例化(調用構造函數)對象時初始化

 

4.靜態成員的初始化的創建過程(本文重點)

當一個類當中包含了靜態成員時,程式內部是如何初始化靜態成員的呢?

4.1代碼示例說明1

 如運行上圖的程式,對於這種情況實際上即使是在程式運行時該類中的靜態成員是沒有被創建(初始化的)。之所以是這種情況,因為程式中靜態成員對應的類型並沒有在任何位置出現過訪問該類型的代碼。而靜態成員的創建是在第一次訪問這個類型時創建的。

 

4.2代碼示例說明2

   在遵循靜態成員的創建原則後,此圖對代碼進行改動後包含了對類型的訪問,那麼這個時候靜態成員是會被創建的。

  從直觀的代碼上來看,很顯然會產生一個對靜態成員初始化的誤解,因為代碼中的靜態成員在聲明時已經進行初始化賦值的操作。其實這種方式只是一種語法糖,是為了方便程式員給的簡單語法。實際上對於類型內部的欄位賦值是通過構造函數來完成的。

  我們現在思考一個問題:上圖代碼中並沒有編寫任何的構造函數,那麼靜態成員是如何進行初始化賦值的呢?

  通過一般的調試時並看不出程式內部的執行過程,也很難找尋問題的答案。此處為了探尋上述的問題我可以通過反編譯工具查看下上圖中反編譯後的代碼。如圖:

   上圖中我們可以看到通過反編譯後MyClass內部包含了一個靜態的構造函數並且為靜態成員進行賦值。此處可以得到一個結論:當在類中定義靜態成員的時候,實際上也定義了一個靜態構造函數。

  

  根據反編譯代碼的情況我們將靜態構造函數顯示的寫在代碼中調試,來驗證下靜態構造函數是否被調用,然後觀察下實例成員和靜態成員初始化的順序。如圖:

  

   根據上圖中的演示可以看出靜態構造函數被調用,並且會先調用靜態構造函數然後在調用實例構造函數。

 

5.關於靜態構造函數需要註意強調的幾點

  1. 靜態構造函數的定義上:不能有訪問修飾符並且必須無參,一個類或結構當中只能有一個構造函數,不允許重載和繼承。
  2. 靜態構造函數調用上:靜態構造函數在編寫代碼時不能像實例構造函數那樣直接調用,它的調用是由公共語言運行時(CLR)調用。並且靜態構造函數只會調用一次。

以下代碼運行圖驗證靜態構造函數只會調用一次的情況:

 

使用建議:

  儘量少使用靜態成員,因為靜態成員的生命周期是在應用程式結束後釋放的,然而GC(垃圾回收)沒有對其進行記憶體的回收管理。促使會上時間的占用記憶體,並且會產生一些記憶體垃圾。

學習感想:

   看似使用簡單的靜態特性,有人運用設計出了軟體模式的單例模式。淬煉堅實的基本功永遠都不算晚,個人覺得編程最難的是在運用,就算學會在高端的技術如果不會組合運用,也還是沒有達到真正掌握的程度。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、整體說明 tomcat需要完成兩件事情: 接受外部HTTP請求 載入servlet,並且把請求傳給Servlet進行處理。 整體可以抽象為如下: 二、整體代碼架構 在tomcat的代碼中抽象了以下三個類: Server類,代表tomcat實例 Connector類,代表HTTP監聽器(上圖中的H ...
  • 本篇文章分享看題目就知道是寫給初學者的,學的比較好的小伙伴也可以將自動演算法等一些知識給加進去,希望對大家有幫助! 好了,當我們所有的準備工作做好之後,我們就可以來編寫我們的C語言連連看游戲了! 其實這個游戲設計起來真的是很簡單的一種,本例用到的知識點主要有:數組,結構體,分支結構,圖形庫函數。 游戲 ...
  • a=['序號',1,2,3,4,5] b=['成本',20,45,12,34,67] import pandas c=pandas.Series(a) d=pandas.Series(b) e=pandas.DataFrame(list(zip(c,d))) print(e) 0 1 0 序號 成本 ...
  • HTTP 非同步風格伺服器 # http_server.php $http = new Swoole\Http\Server("0.0.0.0", 9501); // 設置伺服器運行參數 $serv->set(array( 'daemonize' => 1, // 作為守護進程運行,需同時設置log_ ...
  • 【一、項目目標】 通過Python爬取QQ音樂數據(一)我們實現了獲取 QQ 音樂指定歌手單曲排行指定頁數的歌曲的歌名、專輯名、播放鏈接。 此次我們在之前的基礎上獲取QQ音樂指定歌曲的歌詞及前15個精彩評論。 【二、需要的庫】 主要涉及的庫有:requests、json、html 【三、項目實現】 ...
  • 使用原始django,太過於笨重和雜多nginx是一個輕量級的web伺服器,在處理靜態資源和高併發有優勢uwsgi是一個基於python的高效率的協議,處理後端和動態網頁有優勢所以這裡採用靜態網頁交給nginx解析,動態網頁交給uwsgi解析,並且nginx配置ssl,即可以使用出高安全,高效率的部 ...
  • C# 實現TXT文檔轉 代碼: public DataTable TXTToDataTable(string fileName, string columnName) { DataTable dt = new DataTable(); FileStream fs = new FileStream(f ...
  • C#類型名稱 說明 取值 .NET框架類型 預設值 sbyte 8位有符號整數 -128~127 System.SByte 0 byte 8位無符號整數 0~255 System.Byte 0 short 16位有符號整數 -32768~32767 System.Int16 0 ushort 16位 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...