目錄
2 out
3 ref
5 Paras
首頁 後端開發 C#.Net教程 .NET框架- in ,out, ref , paras使用的程式碼總結

.NET框架- in ,out, ref , paras使用的程式碼總結

Mar 18, 2017 pm 01:45 PM

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);
//调用reviseModel
reviseModel(model.a); //model.a仍然=10;by-value
reviseMode(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裡,

Hash#Map

// 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),带有这个参数的函数,只需要一个版本,这样解决了因为个数不一致而导致的多个重载版本,
在客户端调用时,将属性参数一一列数即可。

以上是.NET框架- in ,out, ref , paras使用的程式碼總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡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

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1273
29
C# 教程
1252
24
vue3中怎麼透過ref取得元素節點 vue3中怎麼透過ref取得元素節點 May 16, 2023 pm 12:25 PM

透過ref取得元素節點ref在vue2中可以說簡化js原生的document.getElementById("#id")操作。當然在vue3中也一樣首先,給你想要取得到的元素一個ref屬性然後,再將這個ref物件建立出來,就可以存取到他的值但是。這樣在setup裡邊可以訪問,但是直接打印出來的值為null........由於setup函數的執行時間要先於html標籤的渲染,所以我們不能直接在setup函數中初始化box標籤。在生命週期函數中setup函數在beforeCreat

vue3使用ref的效能警告問題怎麼解決 vue3使用ref的效能警告問題怎麼解決 May 13, 2023 pm 03:10 PM

vue3使用ref的效能警告問題使用ref的效能警告碼如下import{ref,shallowRef}from"vue";importTodoListfrom"./components/TodoList.vue";importRatefrom"./components/Rate.vue";lettabs={ TodoList,Rate}letcurrentTabComponent=ref(TodoList)警告runtime-core.

vue3取得ref實例結合ts的InstanceType問題怎麼解決 vue3取得ref實例結合ts的InstanceType問題怎麼解決 May 20, 2023 pm 10:59 PM

vue3取得ref實例結合ts的InstanceType有時候我們模板引用,但是在使用的時候,ts提示卻不行,沒有提示組件通過defineExpose暴露的方法名稱,雖然這不是很影響,但是可以解決還是可以解決下~import {ref}from'vue'constsayHello=()=>(console.log('我會說hello'))defineExpose({sayHello})然後我們在父級使用,輸入完成MyModalR

vue3中ref綁定dom或元件失敗的原因為何及怎麼解決 vue3中ref綁定dom或元件失敗的原因為何及怎麼解決 May 12, 2023 pm 01:28 PM

vue3ref綁定dom或元件失敗原因分析場景描述在vue3中常用到使用ref綁定元件或dom元素的情況,很多時候,明明使用ref綁定了相關元件,但是經常ref綁定失敗的情況。 ref綁定失敗情況舉例ref綁定失敗的絕大多數情況是,在ref和元件綁定的時候,該元件還未渲染,所以綁定失敗。或是元件剛開始未渲染,ref未綁定,當元件開始渲染,ref也開始綁定,但是ref和元件並未綁定完成,這個時候使用元件相關的方法就會出現問題。 ref綁定的元件使用了v-if,或他的父元件使用了v-if導致頁面

Vue3中的ref和reactive怎麼使用 Vue3中的ref和reactive怎麼使用 May 12, 2023 pm 05:34 PM

一、是什麼ref和reactive是Vue3中用來實現資料響應式的API一般情況下,ref定義基本資料型,reactive定義引用資料型別二、先聊reactivereactive定義引用資料型別(以物件和陣列舉例),它能夠將複雜資料類型的內部屬性或資料項宣告為響應式數據,所以reactive的響應式是深層的,其底層是透過ES6的Proxy來實現資料響應式,相對於Vue2的Object.defineProperty,具有能監聽增刪操作,能監聽物件屬性的變化等優點使用reactive定義物件數

vue3+ts中怎麼使用ref與reactive指定型別 vue3+ts中怎麼使用ref與reactive指定型別 May 10, 2023 pm 07:19 PM

ref的基礎特性ref約等於reactive({value:x})ref()可以定義時無參數,第一次賦值任意型,然後不能增加屬性constrefa=ref(6)constrcta=reactive({value:12 })console.log('refa:',refa)//RefImpl{...}console.log('refa:',refa.value)//6console.log('rcta:&#3

vue3的ref、isRef、toRef、toRefs、toRaw怎麼用 vue3的ref、isRef、toRef、toRefs、toRaw怎麼用 May 10, 2023 pm 08:37 PM

1.refref屬性除了能夠取得元素外,也可以使用ref函數,建立一個響應式數據,當資料值改變時,視圖會自動更新。 import{ref}from'vue'letstr:string=ref('我是張三')constchang=()=>{str.value='我是鑽石王老五'console.log(str.value)}{ {str}}修改值2、isRef檢查變數是否為一個被ref包裝過的對象,如

深入詳解React中的ref 深入詳解React中的ref Jan 05, 2023 pm 09:13 PM

透過這篇文章的學習,你將收穫 React ref 的基本和進階用法,並且能夠理解 React 內部是如何處理 ref 的,並透過一個小 Demo + 提問的方式帶你更加深刻地理解 ref 的底層原理

See all articles