ホームページ  >  記事  >  バックエンド開発  >  .NET Framework - in、out、ref、paras で使用されるコードの概要

.NET Framework - in、out、ref、paras で使用されるコードの概要

黄舟
黄舟オリジナル
2017-03-18 13:45:142383ブラウズ

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

1 in

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 になります。オブジェクトのプロパティを変更できることがわかります。

2 out

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

3 ref

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

オブジェクトモデルの属性 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 では、

Hash

Map

// 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);
        }
        }

问题来了,当查询再新加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 サイトの他の関連記事を参照してください。

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