目錄
2 out
3 ref##ref關鍵字用於改變參數傳遞,將by value修改為by reference傳值,原來是by reference傳遞的,加上ref還是不加ref,效果是一樣的。
那麼,我就把params的用處,我經歷的這個過程說一下。
首頁 後端開發 C#.Net教程 C# in ,out, ref , paras用處的詳細介紹

C# in ,out, ref , paras用處的詳細介紹

Mar 04, 2017 am 11:06 AM

C#.net 提供的4個關鍵字,in,out,ref,paras開發中會常用到,那麼它們如何使用呢? 又有什麼區別?

## 1 in

in只用在委託與介面中;

範例:

       //测试模型
       class Model
        {            
        public int a { get; set; }            
        public Model(int a)
            {                
            this.a = a;
            }
        }//创建3个实例List<Model> modelList= new List<Model>() 
{ new Model(1), new Model(4), new Model(6) };//调用foreach接口,试着操作3个实例,赋值为nullmodelList.ForEach(e=>e=null); 

//查看结果://modelList的取值不变。
登入後複製

分析原因,ForEach的參數是委託函數:

//ForEach方法:public void ForEach(Action<T> action);//委托声明:public delegate void Action<in T>(T obj);
登入後複製

委託是泛型的,類型T前面加了一個關鍵字in,因為有關鍵字in,所以T obj是不能被修改的。

嘗試測試:

//修改元素e的属性amodelList.ForEach(e=>{e.a*=2;});
登入後複製

結果每個元素都乘以2,變成2,8,12。可知,可以修改物件的屬性。

2 out

out 關鍵字用法注意:

1)帶有out的形參,在函數定義時,return前必須給函數賦一個值。
2)呼叫函數時,帶有out的參數不必賦一個初始值。
3)out形參傳值是透過引用(by reference)

out使用場景:

在函數傳回多個值時,通常會用out 傳回其中一個

public bool Operation(out Model updateMod)
{
    updateMode = new Model(5);    try{     // my operation
     ...     //
     return true;
    }    catch{      //写入日志
      return false;
    }
}//使用Model um; //未初始化bool rtnMsg = Operation(out um); 
//如果初始化,传值通过reference//分析://返回um,如果rntMsg为ture,则um按照预想逻辑被赋值,
//如果rntMsg为false 则um未按照预想逻辑被赋值。
登入後複製

C#.net中有一類TryParse函數,便是out的另一個重要應用。有興趣,請見:透過Parse和TryParse:Try-Parse和Tester-Doer模式

3 ref##ref關鍵字用於改變參數傳遞,將by value修改為by reference傳值,原來是by reference傳遞的,加上ref還是不加ref,效果是一樣的。

例如:

public void reviseModel(int a)
{
  a = 12;
}

Model model = new Model(10);
//调用reviseModelreviseModel(model.a); 
//model.a仍然=10;by-valuereviseMode(ref model.a); 
//编译不过,提示ref后的参数不归类与变量int a;
reviseMode(ref a); 
//如果不给变量a赋一个初始值,
//编译器也是提示:调用前未被赋值的错误
//因此赋值int a= model.a; 
//变量a初始值为10;reviseMode(ref a);
//修改变量a=12;但是model.a的值仍然为10
登入後複製

如何修改物件model中的屬性a,將其變成12呢?

//直接将参数设为Model对象,则函数调用时,传值通过by referencepublic void reviseModel(Model md)
{
  md.a = 12;
}

reviseModel(model );//传值通过by reference
登入後複製

因此,ref關鍵字使用總結:

ref的話,用於處理值變量,如基本類型、結構等,它們不需要被new出來,傳值依照的是值拷貝。


1)ref 後的變數,如果是值型別(value type),那麼加上ref後變成依照by reference傳值;

2)ref 後的變數,如果是引用型別(reference type),那麼加上ref與不加沒有任何差別;

3)ref後的變數,使用前必須賦值

4)ref後的變數不能是引用類型的屬性

以上是基本的分析,在使用上就夠了,如果想更深入的分析這個問題,請繼續。

4 深入探討out ref

主要分析out ref 到底有何用,不用他們會有什麼影響。

1) C#中有一類方法,名字叫作Try…,如Int.TryParse,它傳回一個bool值,嘗試解析一個字串,如果成功解析為整數,則傳回true,得到的整數作為第二個out的int被傳出。

見分析文章 

異常設計準則
透過Parse和TryParse:Try-Parse和Tester-Doer模式
從文章中看出,相較於沒有out參數的次方法Parse,如果解析字串失敗,則會拋出一個參數錯誤的異常。

用Try…方法寫出來的程式碼比try…catch寫出來的

要簡潔

,於是這也變成了out參數使用的一個常用場景。 2) Java和C#比較

在Java裡,HashMap

// HashMap<K, V> map;
// K key;
V val = map.get(key);if (val != null) {
  // ...}
登入後複製

但val == null,既可能是該map裡尚未有鍵為該key的鍵值對,也可能是已經有該鍵值對了但是其值為null。

要區分兩者,HashMap提供了containsKey()方法。所以正確的寫法是這樣的:

// HashMap<K, V> map;
// K key;if (map.containsKey(key)) {
  V val = map.get(key);
  // ...}
登入後複製

containsKey()跟get()的內部操作幾乎是一模一樣的,都要做一次hash查找,只是返回了查找結果的不同部分而已。也就是說按照這種「正確寫法」來寫的話,訪問一次HashMap就有雙倍開銷了。杯具!

C#有許多這種細節設計比Java更貼心。看C#用out關鍵字如何改進這個問題。

System.Collections.Generic.Dictionary

TryGetValue:
Dictionary(TKey, TValue).TryGetValue Method (TKey, TValue) (System.Collections.Generic)public bool TryGetValue(
    TKey key,    out TValue value
)ParameterskeyType: TKey
The key of the value to get.

valueType: TValue
登入後複製

利用這個方法,上面的Java程式碼對應的C#版就可以寫成:

// Dictionary<TKey, TValue> dict;
// TKey key;
TValue val;if (dict.TryGetValue(key, out val)) {
  // ...}
登入後複製

這就把ContainsKey與Item[ Key]的語意結合了起來,把一次hash查找能找到的資訊一口氣都回傳出來,從源頭避免了「兩次查找」的冗餘操作,有利於程式的表現。

C#.net中提供了一個關鍵字params,以前都不知道有這個關鍵字,有一次,同事看到我的幾版重載函數後,淡定地和我說了一句,哥呀,你可以用params,後來查了查,現在常用習慣了,這不剛才又把之前寫的幾版都拿掉了,又用params重構了一下。

5 Paras

那麼,我就把params的用處,我經歷的這個過程說一下。

5.1 問題的需求

在客戶端,客戶經常會變動查詢的字段,前幾天還是根據4個關鍵字段去伺服器查詢幾個模型呢,今天,又想加1個查詢字段。


根據4個關鍵字段的查詢方法:

        public void GetPlansByInputControl(string planState, string contactno,DatePair dp)
        {       
            string planStat = "";            
            switch (planState)
            {                case "...":
                    planStat = "...";                    
                    break;                
                    case "...":
                    planStat = "...";                    
                    break;
            }
                plans = getPlansWithCondition(Convert.ToDateTime(dp.startValue), 
                Convert.ToDateTime(dp.endValue), planStat, contactno);

        }
登入後複製

調用的getPlansWithCondition方法為

        private List<MPartPlan> getMPartPlansWithCondition(DateTime dateTime, DateTime dateEndTime, string planStat, string contactNo)
        {            var conditions = new CslSqlBaseSingleTable();
            conditions.AddCondition("RequireStartDate", dateTime, DataCompareType.GreaterOrEqual);
            conditions.AddCondition("RequireStartDate", dateEndTime, DataCompareType.LessOrEqual);
            conditions.AddCondition("OrderCode", contactNo, DataCompareType.Equal);            
            if (!string.IsNullOrEmpty(planStat))
            {
                conditions.AddCondition("PlanState", planStat, DataCompareType.Equal);
            }            return _cslMPartPlan.QueryListInSingleTable(typeof(MPartPlan), 
            conditions);
        }
        }
登入後複製

問題來了,當查詢再新加1個字段時,你難道還再重載一個版本嗎?

5.2 應用params

 private List<MPartPlan> getMPartPlansWithCondition(DateTime dateTime, DateTime dateEndTime, string planStat, 
 string contactNo,string newField);
登入後複製

當C#提供了params後,當然不用,直接將getMPartPlansWithCondition改寫為如下

private List<MPartPlan> getMPartPlansWithCondition(params object[] queryConditions);
{
   queryConditions[0]
   queryConditions[1]
   queryConditions[2]
   queryConditions[3]
   queryConditions[4]
   //放到字典中dict

   sqlQuery(dict);
}
登入後複製

以後隨意添加查詢字段,只要修改下這個函數就行了,不用增刪重載版! ! !

客戶端調用,直接加一個字段就行

_bsl.GetPlansByInputControl(field1, field2,field3,field4,field5);
登入後複製

5.3 總結

queryFun(params object[] objs),帶有這個參數的函數,只需要一個版本,這樣解決了因為個數不一致而導致的多個重載版本,
在客戶端調用時,將屬性參數一一列數即可。

C#.net 提供的4個關鍵字,in,out,ref,paras開發中會常用到,那麼它們如何使用呢? 又有什麼區別?

 以上就是C# in ,out, ref , paras用處的詳細介紹的內容,更多相關內容請關注PHP中文網(www.php.cn)!


#
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

使用 C# 的活動目錄 使用 C# 的活動目錄 Sep 03, 2024 pm 03:33 PM

使用 C# 的 Active Directory 指南。在這裡,我們討論 Active Directory 在 C# 中的介紹和工作原理以及語法和範例。

C# 序列化 C# 序列化 Sep 03, 2024 pm 03:30 PM

C# 序列化指南。這裡我們分別討論C#序列化物件的介紹、步驟、工作原理和範例。

C# 中的隨機數產生器 C# 中的隨機數產生器 Sep 03, 2024 pm 03:34 PM

C# 隨機數產生器指南。在這裡,我們討論隨機數產生器的工作原理、偽隨機數和安全數的概念。

C# 資料網格視圖 C# 資料網格視圖 Sep 03, 2024 pm 03:32 PM

C# 資料網格視圖指南。在這裡,我們討論如何從 SQL 資料庫或 Excel 檔案載入和匯出資料網格視圖的範例。

C# 中的階乘 C# 中的階乘 Sep 03, 2024 pm 03:34 PM

C# 階乘指南。這裡我們討論 C# 中階乘的介紹以及不同的範例和程式碼實作。

C# 中的模式 C# 中的模式 Sep 03, 2024 pm 03:33 PM

C# 模式指南。在這裡,我們討論 C# 中模式的介紹和前 3 種類型,以及其範例和程式碼實作。

C# 中的質數 C# 中的質數 Sep 03, 2024 pm 03:35 PM

C# 質數指南。這裡我們討論c#中素數的介紹和範例以及程式碼實作。

c#多線程和異步的區別 c#多線程和異步的區別 Apr 03, 2025 pm 02:57 PM

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

See all articles