C#.net には、in、out、ref、paras という 4 つのキーワードがあり、開発ではよく使用されますが、その違いは何ですか?
in は Delegate と でのみ使用されますインターフェイス;
例:
//测试模型 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 が含まれているため、したがって、T obj は変更できません。
テストを試してください:
//修改元素e的属性amodelList.ForEach(e=>{e.a*=2;});
結果は、各要素が 2 倍され、2、8、12 になります。オブジェクトのプロパティを変更できることがわかります。
out キーワードの使用上の注意:
1) out のない仮パラメータの場合、関数の定義時に return の前に値を関数に割り当てる必要があります。
2) 関数を呼び出すとき、out のないパラメータには初期値を割り当てる必要はありません。
3) out 仮パラメータ は、値 を参照によって渡します (バイリファレンス)
out の使用シナリオ:
関数が複数の値を返すとき、通常、out はそのうちの 1 つを返すために使用されます
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未按照预想逻辑被赋值。
TryParse のタイプがありますC#.net の関数。これも out の重要なアプリケーションです。興味のある方は、以下を参照してください: Perse と TryParse を通して: Try-Parse と Tester-Doer モード
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对象,则函数调用时,传值通过by referencepublic void reviseModel(Model md) { md.a = 12; } reviseModel(model );//传值通过by reference
ref は、基本型、構造体などの値変数を処理するために使用されます。それらは新しいものである必要はなく、値の転送は値のコピーに基づいています。
4 out ref についての詳細な議論
主に out ref の使用法と、それらが使用されない場合にどのような影響があるかを分析します。 1) C# には、Int.TryParse などの Try... というメソッドのクラスがあり、ブール値を返し、文字列が整数に解析されると true を返します。取得した整数は2番目として使用され、outのintが渡されます。分析記事を参照
例外設計ガイドライン
Parse および TryParse を通じて: Try-Parse モードと Tester-Doer モード
記事からわかるように、out パラメーターを使用しない 2 番目のメソッド Parse と比較して、文字列の解析が失敗した場合はスローされます。パラメータエラー例外。
であるため、これは out パラメーターを使用する一般的なシナリオとなっています。 2) Java と C# の比較
Java では、
HashMap// HashMap<K, V> map;
// K key;
V val = map.get(key);if (val != null) {
// ...}
// HashMap<K, V> map; // K key;if (map.containsKey(key)) { V val = map.get(key); // ...}
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 と Items[Key] のセマンティクスを組み合わせて、ハッシュ検索を実行します。検索できるすべての情報が一度に返されるため、ソースからの「二重検索」という冗長な操作が回避され、プログラムのパフォーマンスに役立ちます。
C#.net にはキーワード params が用意されています。私はこれまでこのキーワードが存在することを知りませんでした。あるとき、同僚が私のオーバーロードされた関数のいくつかのバージョンを見た後、穏やかに私にこう言いました。チェックしたところ、以前のバージョンをすべて削除し、params を使用してリファクタリングしました。
5 Paras5.1 問題の要件
クライアント側では、顧客はクエリ フィールドを頻繁に変更します。数日前、顧客は 4 つのキー フィールドに基づいて複数のモデルをクエリするために、今日別のクエリ フィールドを追加したいと考えています。
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 Framework - in、out、ref、paras で使用されるコードの概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。