網站首頁 編程語言 正文
摘一段來自官網的說明 :方法的參數列表中使用 ref 關鍵字時,它指示參數按引用傳遞,而非按值傳遞。 ref 關鍵字讓形參成為實參的別名,這必須是變量。 換而言之,對形參執行的任何操作都是對實參執行的。
大體意思就是將實慘的引用作為參數傳遞,如果入參不加ref修飾,本身傳遞的是實參的值到方法中。
那什么是值,什么是引用?大體可以理解為堆棧的區別,在.net中大多數實例存在于托管堆棧中。struct,int32,int64,double,enum等數據類型聲明的實例存在棧中,而string,class,delegate等存在于堆中。前者一般稱為值類型,后者則叫做引用類型,那么引用類型和值類型在內存中的大概圖如下:
可以看到引用類型被存儲的時候真正內容存在堆中,而在stack中存儲了一個堆中地址的引用指向堆中真正內容。
ref修飾入參的常用場景
當我們希望一個已有返回值的方法能夠修改我一個外部基本類型的值的時候,我們可以將該參數加上ref關鍵字作為入參。具體原理其實就是將棧中具體的值替換為了棧的引用,說白了就是地址,幻想一下本來你高考作弊只是后臺改了一下自己成績和學霸一樣,學霸的人生沒有受到影響,現在你干脆把學霸的試卷改成了自己名字,學霸直接被你影響只能進廠打螺絲了,當然這個比喻不是很貼切,大家理解到意思就行。
那么為什么引用類型的入參我們不需要要添加ref?因為從上圖我們能看出來棧中存儲的本來就是引用類型的地址,所以引用類型不需要添加ref關鍵字,當你在方法內部修改了入參的一些屬性值,外面的實慘依舊會受到影響。
引用類型添加ref的作用是啥?
我們在實際開發中還是能夠碰到一些引用類型添加ref的場景。其實道理也是一樣的,就是將引用類型的棧的地址傳遞到了方法中,那么和不添加有啥區別?我們來看看下面的代碼:
Student student1 = new Student("Jack");
Student student2 = new Student("Lucy");
WithoutRef(student1);
WithRef(ref student2);
Console.WriteLine($"不帶ref的方法---{student1.Name}");
Console.WriteLine($"帶ref的方法---{student2.Name}");
Console.Read();
//不帶ref的方法
static void WithoutRef(Student stu)
{
stu.Name = "Bruce";
}
//不帶ref的方法
static void WithRef(ref Student stu)
{
stu.Name = "Bruce";
}
public class Student
{
public Student(string name)
{
Name = name;
}
public string Name { get; set; }
}
可以看到結果一樣的,兩個實例的名字都變了
那我們再看看下面的代碼:
Student student1 = new Student("Jack");
Student student2 = new Student("Lucy");
WithoutRef(student1);
WithRef(ref student2);
Console.WriteLine($"不帶ref的方法---{student1.Name}");
Console.WriteLine($"帶ref的方法---{student2.Name}");
Console.Read();
//不帶ref的方法
static void WithoutRef(Student stu)
{
stu = new Student("Bruce");
}
//不帶ref的方法
static void WithRef(ref Student stu)
{
stu = new Student("Bruce");
}
public class Student
{
public Student(string name)
{
Name = name;
}
public string Name { get; set; }
}
我們發現第一個不帶ref的方法名字沒有發生變化。
代碼的變化就是第二個例子重新new了一下,我們根據上面的原理分析就能知道為啥。由于ref將引用類型的棧地址傳遞過去了,new關鍵字大體就是在堆中開辟一個新空間,然后將空間地址存儲到棧中,由于ref將棧地址傳遞過來了,所以就將棧中的存儲地址替換為了新開辟的堆地址了,而不帶ref的引用類型本身傳遞的只是堆中地址的引用,所以new關鍵字等于說將形參重新開辟空間和分配了,和實參已經不是同一個地方了。
總結
ref傳遞的是棧地址
不帶ref傳遞的是棧中存儲的值,可能是一個值,也可能是一個地址引用。
原文鏈接:https://www.cnblogs.com/qwqwQAQ/p/16902885.html
相關推薦
- 2022-07-06 Android中ViewFlipper和AdapterViewFlipper使用的方法實例_Andr
- 2023-09-12 SpringBoot整合MQTT(MqttClient)
- 2023-02-05 前端面試學習中幾個常見有用的知識點_經驗交流
- 2022-05-14 python中opencv支持向量機的實現_python
- 2022-07-18 數據結構 III 深入理解棧和隊列實現
- 2021-12-10 redis服務器cpu100%的原因和解決方案
- 2022-08-15 使用element中el-table設置type=“expand“展開行隱藏小箭頭的方法(列表單選、
- 2021-12-03 Go并發編程中sync/errGroup的使用_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支