C#.net が提供する 4 つのキーワード、in、out、ref、paras は開発でよく使用されますが、その違いは何ですか?
は委任でのみ使用されます。インターフェイス内;
例:
//测试模型 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);
デリゲートは汎用であり、キーワード in が型 T の前に追加されます。キーワード in があるため、T obj は変更できません。
テストを試してください:
//修改元素e的属性amodelList.ForEach(e=>{e.a*=2;});
結果は、各要素が 2 倍され、2、8、12 になります。オブジェクトのプロパティを変更できることがわかります。
out キーワードの使用上の注意:
1) out のない仮パラメータの場合、関数を定義するときは、戻る前に関数に値を割り当てる必要があります。
2) 関数を呼び出すとき、out のないパラメータには初期値を割り当てる必要はありません。
3) out 仮パラメータの値は参照によって渡されます (by Reference)
out の使用シナリオ:
関数が複数の値を返すとき、通常、そのうちの 1 つを返すために 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未按照预想逻辑被赋值。
TryParse のタイプがありますC#.net の関数。これも out の重要なアプリケーションです。興味のある方は、以下を参照してください: Perse と TryParse を通して: Try-Parse と Tester-Doer モード
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对象,则函数调用时,传值通过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) { // ...}
でも val == null の場合、マップ内にキーとのキーと値のペアが存在しないか、またはすでにキーが存在する可能性があります。値ペアですが、その値は null です。
この 2 つを区別するために、HashMap は containsKey() メソッドを提供します。したがって、正しい書き方は次のようになります:// 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); } }
問題は、新しいフィールドがクエリに追加されたときに、バージョンを再読み込みするかということです。
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)、このパラメータを持つ関数は 1 つのバージョンのみを必要とし、一貫性のない数値による複数のバージョンのオーバーロードの問題を解決します。
クライアントで呼び出すときは、属性パラメータを 1 に設定します。1 つにカウントするだけです。カラム。
C#.net が提供する 4 つのキーワード、in、out、ref、paras は開発でよく使用されますが、その違いは何ですか?
上記は C# の in、out、ref、 paras 詳細については、PHP 中国語 Web サイト (www.php.cn) の関連コンテンツに注目してください。