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里,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),带有这个参数的函数,只需要一个版本,如许处理了由于个数不一致而致使的多个重载版本,
在客户端挪用时,将属性参数一一列数即可。
以上就是.NET框架- in ,out, ref , paras运用的代码总结的细致内容,更多请关注ki4网别的相干文章!