ホームページ >バックエンド開発 >C#.Net チュートリアル >C# の in、out、ref、paras の使用方法の詳細な紹介

C# の in、out、ref、paras の使用方法の詳細な紹介

黄舟
黄舟オリジナル
2017-03-04 11:06:454024ブラウズ

C#.net が提供する 4 つのキーワード、in、out、ref、paras は開発でよく使用されますが、その違いは何ですか?

1 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);

デリゲートは汎用であり、キーワード in が型 T の前に追加されます。キーワード in があるため、T obj は変更できません。

テストを試してください:

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

結果は、各要素が 2 倍され、2、8、12 になります。オブジェクトのプロパティを変更できることがわかります。

2 out

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 モード

3 ref

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

オブジェクトモデルの属性 a を変更して 12 に変更するにはどうすればよいですか?

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

reviseModel(model );//传值通过by reference

そのため、 ref キーワードの使用の概要:

ref は、基本型、構造体などの値変数を処理するために使用されます。それらは新しいものである必要はなく、値の転送は値のコピーに基づいています。

1) ref の後の変数、それが値型 (値型) の場合、ref を追加した後、参照によって渡された値になります。

2) ref の後の変数、それが参照型 (reference 型) の場合。 type) の場合、ref を追加する場合と追加しない場合に違いはありません

3) ref の後の変数には、使用する前に値を割り当てる必要があります

4) ref の後の変数は参照型属性にすることはできません

上記は次のとおりです。基本的な分析だけで十分です。この問題をさらに深く分析したい場合は、続けてください。

4 out ref についての詳細な議論

主に out ref の使用法と、それらが使用されない場合にどのような影響があるかを分析します。

1) C# には、Int.TryParse などの Try... というメソッドのクラスがあり、ブール値を返し、文字列が整数に解析されると true を返します。取得した整数は2番目として使用され、outのintが渡されます。

分析記事を参照
例外設計ガイドライン
Parse および TryParse を通じて: Try-Parse モードと Tester-Doer モード
記事からわかるように、out パラメーターを使用しない 2 番目のメソッド 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 の場合、マップ内にキーとのキーと値のペアが存在しないか、またはすでにキーが存在する可能性があります。値ペアですが、その値は null です。

この 2 つを区別するために、HashMap は containsKey() メソッドを提供します。したがって、正しい書き方は次のようになります:

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

containsKey() と get() の内部操作はほぼ同じです。どちらもハッシュ検索を行う必要がありますが、検索結果の異なる部分を返すだけです。 。つまり、この「正しい書き方」に従って書くと、HashMapに1回アクセスするのに2倍のコストがかかってしまいます。カップ!

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 Paras

それでは、params の使い方と私が行ったプロセスについて話します。

5.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) の関連コンテンツに注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。