C#中ref和out的區(qū)別淺析
在C#中通過(guò)使用方法來(lái)獲取返回值時(shí),通常只能得到一個(gè)返回值。因此,當(dāng)一個(gè)方法需要返回多個(gè)值的時(shí)候,就需要用到ref和out,那么這兩個(gè)方法區(qū)別在哪兒呢?
MSDN:
ref 關(guān)鍵字使參數(shù)按引用傳遞。其效果是,當(dāng)控制權(quán)傳遞回調(diào)用方法時(shí),在方法中對(duì)參數(shù)所做的任何更改都將反映在該變量中。若要使用 ref 參數(shù),則方法定義和調(diào)用方法都必須顯式使用 ref 關(guān)鍵字。
out 關(guān)鍵字會(huì)導(dǎo)致參數(shù)通過(guò)引用來(lái)傳遞。這與 ref 關(guān)鍵字類(lèi)似,不同之處在于 ref 要求變量必須在傳遞之前進(jìn)行初始化。若要使用 out 參數(shù),方法定義和調(diào)用方法都必須顯式使用 out 關(guān)鍵字。
案例:
定義一個(gè)方法,求一個(gè)整數(shù)數(shù)組中的最大值,最小值,和,平均數(shù)。如果是一個(gè)方法只能有一個(gè)返回值,那只能每一個(gè)都得定義一個(gè)方法來(lái)實(shí)現(xiàn),不過(guò)有了ref和out這實(shí)現(xiàn)起來(lái)就方便多了。
ref:
static int GetIntResult(int[] arry, ref float avg, ref int max, ref int min)
{
int sum = 0;
max = arry[0];
min = arry[0];
for (int i = 0; i < arry.Length; i++)
{
sum += arry[i];
if (max < arry[i])
{
max = arry[i];
}
if (min > arry[i])
{
min = arry[i];
}
}
avg = sum / arry.Length;
return sum;
}
然后在控制臺(tái)中試著調(diào)用該方法:
static void Main(string[] args)
{
int[] arr = { 1,2,3,4,5,6,7,8,9};
float avg;
int max;
int min;
int sum = GetIntResult(arr, ref avg, ref max, ref min);
}
此時(shí)編譯器就會(huì)提示畫(huà)紅線,錯(cuò)誤:使用了未賦值的avg,max,min
static void Main(string[] args)
{
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
float avg = 0;
int max = 0;
int min = 0;
int sum = GetIntResult(arr, ref avg, ref max, ref min);
Console.WriteLine("和:{0}\t平均值:{1}\t最大值:{2}\t最小值:{3}", sum, avg, max, min);
Console.Read();
}
運(yùn)行結(jié)果:

總結(jié):
ref這個(gè)關(guān)鍵字告訴c#編譯器被傳遞的參數(shù)值指向與調(diào)用代碼中變量相同的內(nèi)存。這樣,如果被調(diào)用的方法修改了這些值然后返回的話,調(diào)用代碼的變量也就被修改了。
ref 關(guān)鍵字使參數(shù)按引用傳遞。其效果是,當(dāng)控制權(quán)傳遞回調(diào)用方法時(shí),在方法中對(duì)參數(shù)所做的任何更改都將反映在該變量中(avg,max,min的初始值為0,調(diào)用方法后值改變)。若要使用 ref 參數(shù),則方法定義和調(diào)用方法都必須顯式使用 ref 關(guān)鍵字。
out:
換成out之后,上面的方法不再適用,報(bào)錯(cuò),錯(cuò)誤 : 控制離開(kāi)當(dāng)前方法之前必須對(duì) out 參數(shù)“min”和"max"賦值。你會(huì)發(fā)現(xiàn)這里max和min在循環(huán)外并未初始化。所以才會(huì)出錯(cuò)。
修改后代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Wolfy.RefAndOut
{
class Program
{
static void Main(string[] args)
{
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
float avg;//在使用out關(guān)鍵字時(shí),不需要在此處初始化,初始化也不會(huì)影響到方法內(nèi)部的值,所以你初始化沒(méi)用
int max;
int min;
int sum = GetIntResult(arr, out avg, out max, out min);
Console.WriteLine("和:{0}\t平均值:{1}\t最大值:{2}\t最小值:{3}", sum, avg, max, min);
Console.Read();
}
static int GetIntResult(int[] arry, out float avg, out int max, out int min)
{
int sum = 0;
max = arry[0];
min = arry[0];//使用out關(guān)鍵字時(shí),必須在離開(kāi)方法前對(duì)out關(guān)鍵字修飾的參數(shù)初始化
for (int i = 0; i < arry.Length; i++)
{
sum += arry[i];
if (max < arry[i])
{
max = arry[i];
}
if (min > arry[i])
{
min = arry[i];
}
}
avg = sum / arry.Length;
return sum;
}
}
}
結(jié)果和上面一樣。
總結(jié):
out 關(guān)鍵字會(huì)導(dǎo)致參數(shù)通過(guò)引用來(lái)傳遞。這與 ref 關(guān)鍵字類(lèi)似,不同之處在于 ref 要求變量必須在傳遞之前進(jìn)行初始化。若要使用 out 參數(shù),方法定義和調(diào)用方法都必須顯式使用 out 關(guān)鍵字。
結(jié)論:
關(guān)鍵字“ref“和”out”之間的唯一區(qū)別就是關(guān)鍵字”out“不要求調(diào)用代碼初始化要傳遞的參數(shù)值。那么關(guān)鍵字‘ref”什么時(shí)候用呢?當(dāng)您需要確保調(diào)用方法已經(jīng)初始化參數(shù)值的時(shí)候,您就應(yīng)該使用關(guān)鍵字“ref”。在上面例子中,能夠使用“out“是因?yàn)楸徽{(diào)用的方法并不依賴(lài)于被傳遞的變量的值。個(gè)中滋味慢慢體會(huì)......
后話:
在一論壇里面,偶然看到有這樣的帖子,就順便總結(jié)了一下,也算是回憶一下c#基礎(chǔ)知識(shí)吧。
- c#基礎(chǔ)系列之ref和out的深入理解
- C#中out參數(shù)、ref參數(shù)與值參數(shù)的用法及區(qū)別
- .NET/C#利用反射調(diào)用含ref或out參數(shù)的方法示例代碼
- C#方法中參數(shù)ref和out詳解
- 詳解C#中三個(gè)關(guān)鍵字params,Ref,out
- 詳解C#中的out和ref
- C#編程中使用ref和out關(guān)鍵字來(lái)傳遞數(shù)組對(duì)象的用法
- 一看就懂:圖解C#中的值類(lèi)型、引用類(lèi)型、棧、堆、ref、out
- C#中out與ref的區(qū)別實(shí)例解析
- C# ref and out的使用小結(jié)
相關(guān)文章
C#實(shí)現(xiàn)常見(jiàn)加密算法的示例代碼
這篇文章主要為大家詳細(xì)介紹一下C#中一些常見(jiàn)加密算法(Base64編碼、凱撒密碼、Vigenere密碼、DES、AES)以及它們的實(shí)現(xiàn)代碼,感興趣的可以了解一下2022-07-07
詳解C# TimeSpan 計(jì)算時(shí)間差(時(shí)間間隔)
本篇文章主要介紹了C# TimeSpan 計(jì)算時(shí)間差(時(shí)間間隔),非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12
C#如何優(yōu)雅地取消進(jìn)程的執(zhí)行之Cancellation詳解
本文介紹了.NET框架中的取消協(xié)作模型,包括CancellationToken的使用、取消請(qǐng)求的發(fā)送和接收、以及如何處理取消事件2024-12-12
C# 常用協(xié)議實(shí)現(xiàn)模版及FixedSizeReceiveFilter示例(SuperSocket入門(mén))
本文主要介紹了常用協(xié)議實(shí)現(xiàn)模版及FixedSizeReceiveFilter示例。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
Visual Studio中根據(jù)系統(tǒng)區(qū)分引用64位、32位DLL動(dòng)態(tài)庫(kù)文件的配置方法
這篇文章主要介紹了Visual Studio中根據(jù)系統(tǒng)區(qū)分引用64位、32位DLL動(dòng)態(tài)庫(kù)文件的配置方法,本文在VS2008中測(cè)試通過(guò),其它VS版本可以參考下2014-09-09
C#通過(guò)正則表達(dá)式實(shí)現(xiàn)提取網(wǎng)頁(yè)中的圖片
本文給大家分享的是使用C#通過(guò)正則表達(dá)式來(lái)實(shí)現(xiàn)提取網(wǎng)頁(yè)中的圖片的代碼,十分的方便,有需要的小伙伴可以參考下。2015-12-12
Silverlight實(shí)現(xiàn)星星閃爍動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了Silverlight實(shí)現(xiàn)星星閃爍動(dòng)畫(huà),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
c#刪除數(shù)組中符合條件的元素(正確寫(xiě)法)
這篇文章主要介紹了c#刪除數(shù)組中符合條件的元素,分別給大家展示了錯(cuò)誤寫(xiě)法和正確寫(xiě)法,補(bǔ)充介紹了從C#的數(shù)組中刪除指定元素的幾種方法,需要的朋友可以參考下2023-10-10

