C#7.0 ref引用傳遞

1.概要

在工作中大家用到引用類型是非常多的,大家都知道引用類型在使用過程中傳遞的是對象引用并不會發生整個對象復制。而值類型在傳遞的過程中就不一樣了,我曾經在編寫代碼時希望通過值類型來壓低應用程序的內存占用,在高并發的情況大量的對象需要在程序里流轉這個時候看內存監測的時候會發現,內存并沒有變少。雖說值類型能提供很多好處但有一個缺點就是會發生復制,那么如何規避復制這個缺點呢?我們往下看(本文只是簡略的分享,實際上要把這一整塊講明白幾千字是遠遠不夠的)。

2.詳細內容

2.1 ref

在繼續了解C#7.0的ref特性需要了解一些前置知識點,首先是變量和值的區別。

(下圖)變量包含內容:

  • 變量名稱

  • 編譯時類型

  • 當前值

2a7549fd64faec09a6c9ba2c1656a263.png

變量的聲明本質是在內存中開辟一段內存空間,給變量x賦值相當于是覆蓋了之前的值。當變量類型是引用類型時,控件里的值不再是對象本身。而是對象的引用,就是通過內存地址找到對象。(如果加上ref關鍵字,ref的引用和對象引用是不同的概念。通過值傳遞對象引用和通過引用傳遞變量是不同的。)

當把某個變量值復制給另外一個變量時,只是這個值本身發生了復制。這兩個變量依然是獨立的,之后任何一個變量的值修改不會影響另外一個變量。

4767aeac698284a11af8e70476b0a1a1.png

這種方式的值復制,和調用方法時對值參數的操作是相同的:方法實參的值被復制到了另一個新的空間中。

1a557a0d961d4c99b9cf2bdbf9f7a8c6.png

而ref參數的行為與此不同。使用ref參數,不會創建開辟新的空間,而是調用放提供一個現有的包含初始值的空間。可以理解為一個空間同時被兩個地址指向:一個是調用方使用的該變量的表示,另一個是形參的名稱。

d6d94a64d0d3026e872a3caf33c0f18b.png

如果在方法中修改了ref參數的值,即修改了紙上的現有值。當方法返回時,修改的結果就會反回給調用方,因為修改的是同一個命名空間的值。

2.2 ref readonly

前面提到的變量都是可寫變量,以下兩個獨立場景中,只允許ref可寫變量就顯得有些不足了。

  • 可能需要給某個只讀字段添加引用地址,避免復制以提升效率。

  • 可能需要只允許通過ref變量進行只讀訪問。

C#7.2加入了ref readonly解決了上述問題。ref局部變量可以使用readonly進行修飾,得到的結果自然是只讀的,就像只讀字段一樣。不能為只讀變量賦新值,如果它是結構體,則不能修改任何字段或者調用屬性的setter方法。

代碼示例:

public readonly struct Juster{public int Age { get; }public Juster(int age) => Age = age;}

使用readonly的兩處都需要協作:如果調用一個帶有ref readonly返回的方法或者索引器,并且需要將結果保存到一個局部變量中,那么這個局部變量必須由ref readonly修飾。

internal class Class1{static readonly int field = DateTime.UtcNow.Second;static ref readonly int GetJusterTime() => ref field;public void Test() {ref readonly int local = ref GetJusterTime();Console.WriteLine(local);}}

2.3 in參數

C#7.2為方法參數加入了in修飾符,該修飾符的使用方式與ref、out相同,但目的不同。一個帶有in修飾符參數,可以通過引用傳遞避免復制提升效率,同時可以保證參數值不被修改。在方法內部,in參數的行為類似于ref readonly局部變量。該變量依然是由調用方傳入的一個內存地址,因此要保證方法不會被修改值,否則修改結果回影響調用方,這樣就違背了in參數的意義。

安全的使用使用in參數:

public static double PublicMethod(Juster juster) {double result = GetScale(in juster);return result + result;}private static double GetScale(in Juster input) => input.Age * input.Age;

這種方式可以防止參數被意外修改,因為方法是私有的,我們可以檢查所有調用方,確定它們不會傳遞哪些在方法執行時可能被修改的參數。在方法GetScale被調用時,每個結構體只會被復制一次,復制之后私有方法調用時都是別名。這樣就把自己的代碼和其他線程中調用方的任何修改,或者其他方法的副作用隔離開來了。

使用建議:

  • 只有確定性能提升客觀,采用in參數,例如使用大型結構體。

  • 在公共api中盡量避免使用in參數,除非即便參數值發生變化,方法也能正確執行。

  • 可以考慮通過公共方法作為防止參數被修改的外部屏障,然后再內部私有方法中使用in參數來減少復制。

  • 對于采用in參數的方法,在調用時考慮顯式給出in修飾符。

性能相關測試

https://cloud.tencent.com/developer/article/1402446

https://www.cnblogs.com/BeanHsiang/p/8687780.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281322.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281322.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281322.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue+Axios同步請求

axios本身是沒有同步請求的,要實現同步請求,用到的是ES7的async和await ES7的異步特性async / await async用于聲明一個函數是異步的,await用于聲明在一個異步函數中等待語句執行完畢。也就是說await只能在async函數中使用。簡單示例如下&a…

關于vue執行打包后,如何在本地瀏覽問題

最近一個人在搗鼓vue,寫完項目后發現在npm run dev下可以正常訪問,bulid之后卻一片空白,查看console出現許多Failed to load resource: net::ERR_FILE_NOT_FOUND。恩,看了下網上評論找到了正確的方法 webpack.prod.conf.js 中outp…

ELFhash

字符串哈希算法(以ELFHash詳解) 更多字符串哈希算法請參考:http://blog.csdn.net/AlburtHoffman/article/details/19641123 先來了解一下何為哈希: 哈希表是根據設定的哈希函數H(key)和處理沖突方法將一組關鍵字映射到一個有限的地…

android面試詳解

前臺就是和用戶交互的進程 可見進程例如一個activity被一個透明的對話框覆蓋,該activity就是可見進程 服務:service進程 后臺一個activity按了home按鍵就是從前臺退回到后臺 標準模式:不管任務棧是否存在相同的activity都會創建一個新的activ…

element-ui Notification重疊問題,原因及解決辦法

在1個方法中調用兩次this.$notify方法,會出現通知框重疊的問題 methods: {checkLogin: function () {if (this.username ) {this.$notify({title: 提示,message: 請輸入用戶名})}if (this.password ) {this.$notify({title: 提示,message: 請輸入用戶密碼})}}}網上…

Visual Stiudio使用技巧

技巧1 自動生成帶參構造函數當我們在編寫代碼時會經常遇到初始化一個的類,需要通過構造函數進行對象初始化。那么這個時候我們可能會需要逐個去手動寫,這樣的工作即重復又無趣。如果是在項目非常緊急的情況下還有大量的字段需要與入參一一對應起來簡直太…

js將時間戳格式化為HH:ii:ss的格式

將時間戳格式化為 HH:ii:ss的格式 <html> <head> </head> <body><span id"time"></span><script>var timestamp Date.parse(new Date())/1000;var time_old Date.parse(new Date())/1000;timeAdd()/*** purpose : …

Struts 整合 SpringMVC

Struts 整合 SpringMVC 過程&#xff1a;這篇文章是我在整合過程中所做的記錄和筆記 web.xml &#xff1a;篩選器機制過濾 原機制是攔截了所有 url &#xff0c;即 <url-pattern>/*</url-pattern>新機制為了將 structs2 的 url 與 SpringMVC 的 url 區分開來&#…

Vue保持用戶登錄及權限控制

vue-router-power-demo 核心內容有兩點&#xff1a; 一是保持用戶登錄狀態&#xff0c;二是根據登錄用戶的角色動態掛在路由 使用vuex保持用戶登錄 點擊登錄按鈕&#xff0c;使用vuex的actions分發登錄操作&#xff0c;發送用戶名和密碼到后臺獲取登錄token&#xff0c; 并存…

java B2B2C Springcloud多租戶電子商城系統-Spring Cloud Sleuth

在微服務框架中&#xff0c;一個由客戶端發起的請求在后端系統中會經過多個不同的的服務節點調用來協同產生最后的請求結果&#xff0c;每一個前段請求都會形成一條復雜的分布式服務調用鏈路&#xff0c;鏈路中的任何一環出現高延時或錯誤都會引起整個請求最后的失敗。 愿意了解…

C#性能測試BenchmarkDotnet

1.簡介在我們開發高性能代碼時&#xff0c;需要各種針對性能優化進行編碼。那么如何才能知道我們所加的代碼是否有性能方面的正向優化呢&#xff1f;有了BenchmarkDotNet&#xff0c;做性能對比測試就非常容易了&#xff0c;只需要把你的測試方法加上特性[Benchmark], 想做不同…

Requests獲取連接的IP地址

在接口自動化的時候&#xff0c;需要獲取到連接的本地IP地址&#xff0c;方法如下 1 import requests 2 3 rsp requests.get("http://www.baidu.com", streamTrue) 4 print rsp.raw._connection.sock.getpeername()[0] 5 print rsp.raw._connection.sock.getsockna…

阿里云APP(V4.3) SSH遠程登錄功能設置操作指南

阿里云APP V4.3 發布了&#xff0c;這次的升級&#xff0c;不僅在iOS和android平臺上支持SSH遠程登錄ECS功能&#xff0c;也支持密鑰登錄哦~~~ SSH遠程登錄&#xff0c;這是一個連阿里巴巴自己的技術人員都開心不已的功能&#xff01; 各位攻城獅們&#xff0c;從更新到V4.3的那…

JS專題之節流函數

本文共 2000 字&#xff0c;讀完只需 8 分鐘上一篇文章講了去抖函數&#xff0c;然后這一篇講同樣為了優化性能&#xff0c;降低事件處理頻率的節流函數。 一、什么是節流&#xff1f; 節流函數&#xff08;throttle&#xff09;就是讓事件處理函數&#xff08;handler&#xf…

vue 2.6 插槽v-slot用法記錄

v-slot用法簡記用法示例匿名插槽與具名插槽插槽作用域組件使用插槽動態命名總結用法示例 vue2.6統一了插槽的語法v-slot 匿名插槽與具名插槽 在其他組件中使用child組件 <child><template v-slot:slotName>hello world</template> </child>child組…

Latex排版全解(轉)

Latex排版全解 http://blog.csdn.net/langb2014/article/details/51354238轉載于:https://www.cnblogs.com/yifdu25/p/8338399.html

git-ftp Can't access remote 'ft://...', exiting...問題記錄

環境 服務器&#xff1a;西部數碼虛擬主機 本地系統&#xff1a;windows 10 (LTSC 2019) 軟件&#xff1a; Git Bash&#xff0c;gti-ftp (版本1.6.0) 問題 在使用git ftp init初始化上傳代碼的時候會出現 $ git ftp init fatal: Cant access remote ftp://dmkt:***dmkt.goto…

【Flutter教程】從零構建電商應用(一)

在這個系列中&#xff0c;我們將學習如何使用google的移動開發框架flutter創建一個電商應用。本文是flutter框架系列教程的第一部分&#xff0c;將學習如何安裝Flutter開發環境并創建第一個Flutter應用&#xff0c;并學習Flutter應用開發中的核心概念&#xff0c;例如widget、狀…

為OWA自定義快捷鍵

這篇短文分享一下如何為自己常用的網頁添加自定義功能&#xff0c;例如添加快捷鍵。我這里用一個常用的網站作為范例。它是Outlook Web Access (OWA), 它的地址一般如下。我在寫郵件時希望能用一些快捷鍵來提高工作效率&#xff0c;但系統默認自帶的快捷鍵特別少&#xff0c;而…

數據結構 快速排序

快速排序是對冒泡排序的一種改進&#xff0c;是所有內部排序算法中平均性能最優的排序算法。其基本思想是基于分治法的&#xff1a;在待排序數組L[1...n]中任取一個元素pivot作為基準&#xff0c;從數組的兩端開始掃描。設兩個指示標志&#xff08;low指向起始位置&#xff0c;…