Heim  >  Artikel  >  Backend-Entwicklung  >  .NET Framework – Zusammenfassung des in, out, ref, paras verwendeten Codes

.NET Framework – Zusammenfassung des in, out, ref, paras verwendeten Codes

黄舟
黄舟Original
2017-03-18 13:45:142384Durchsuche

Die vier von C#.net bereitgestellten Schlüsselwörter werden häufig in der Entwicklung verwendet: in, out, ref und paras. Was ist also der Unterschied?

1 in

in wird nur in Delegaten und Schnittstellen verwendet;
Beispiel:

       //测试模型
       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的取值不变。

Analyse des Grundes, der Parameter von ForEach sind DelegateFunktion:

//ForEach方法:public void ForEach(Action<T> action);//委托声明:public delegate void Action<in T>(T obj);

Der Delegat ist generisch und vor dem Typ T wird ein Schlüsselwort in hinzugefügt. Aufgrund des Schlüsselworts in kann T obj nicht geändert werden.

Probieren Sie den Test aus:

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

Als Ergebnis wird jedes Element mit 2 multipliziert und ergibt 2,8,12. Es ist ersichtlich, dass die Eigenschaften des Objekts geändert werden können.

2 out

Hinweise zur Verwendung des Schlüsselworts out:
1) Für formale Parameter ohne out wird beim Definieren der Funktion ein Wert zurückgegeben muss zuvor der Funktion zugewiesen werden.
2) Beim Aufruf einer Funktion muss Parametern ohne out kein Anfangswert zugewiesen werden.
3) Out-Formalparameter Wertübergabe erfolgt durch Referenz (durch Referenz)

Out-Verwendungsszenario:
Wenn eine Funktion mehrere Werte zurückgibt, wird Out normalerweise verwendet, um einen zurückzugeben davon.

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未按照预想逻辑被赋值。

Es gibt eine Art TryParse-Funktion in C#.net, die eine weitere wichtige Anwendung von out ist. Wenn Sie interessiert sind, lesen Sie bitte: Durch Parse und TryParse: Try-Parse- und Tester-Doer-Modi

3 ref

ref-Schlüsselwort wird verwendet, um die Parameterübergabe zu ändern, Änderung nach Wert durch Referenz. Der ursprüngliche Wert wird mit oder ohne Referenz übergeben.

Zum Beispiel:

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

Wie ändere ich das Attribut a im Objektmodell, um es in 12 zu ändern?

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

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

Daher eine Zusammenfassung der Verwendung des Schlüsselworts ref:
ref wird zur Verarbeitung von Wertvariablen wie Grundtypen, Strukturen usw. verwendet. Sie müssen nicht neu sein und Die Wertübertragung basiert auf einer Wertkopie.

1) Die Variable nach ref, wenn es sich um einen Werttyp handelt, wird nach dem Hinzufügen von ref zu einem als Referenz übergebenen Wert.

2) Die Variable nach ref, wenn es sich um eine Referenz handelt Typ (Referenztyp), dann gibt es keinen Unterschied zwischen dem Hinzufügen von ref oder nicht;

3) Der Variablen nach ref muss vor der Verwendung ein Wert zugewiesen werden

4) Der Variablen nach ref kann kein Wert zugewiesen werden eine Referenz Typattribute

Das Obige ist die grundlegende Analyse, die für die Verwendung ausreichend ist. Wenn Sie dieses Problem eingehender analysieren möchten, fahren Sie bitte fort.

4 Ausführliche Diskussion über unsere Schiedsrichter

Analysieren Sie hauptsächlich die Verwendung unserer Schiedsrichter und welche Auswirkungen sie haben, wenn sie nicht verwendet werden.

1) In C# gibt es eine Methodenklasse namens Try..., wie z. B. Int.TryParse. Sie gibt einen Bool-Wert zurück und versucht, eine Zeichenfolge zu analysieren gibt true zurück und die erhaltene Ganzzahl ist. Das int wird als zweites Out übergeben.
Siehe den Analyseartikel
Richtlinien zum Ausnahmedesign
Durch Parse und TryParse: Try-Parse- und Tester-Doer-Modi
Wie aus dem Artikel hervorgeht, im Vergleich zur Untermethode Parse ohne Out-Parameter , wenn beim Parsen die Zeichenfolge fehlschlägt, wird eine Parameterfehlerausnahme ausgelöst.

Mit der Try...-Methode geschriebener Code ist prägnanter als der mit der Try...catch-Methode geschriebene Code, daher ist dies zu einem häufigen Szenario für die Verwendung von Out-Parametern geworden.

2) Vergleich zwischen Java und C#

In Java, HashMap

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

aber val == null , kann es sein, dass es kein Schlüssel-Wert-Paar mit dem Schlüssel in der Karte gibt, oder es kann sein, dass das Schlüssel-Wert-Paar bereits existiert, aber sein Wert null ist.
Um zwischen den beiden zu unterscheiden, stellt HashMap die Methode containsKey() bereit. Die korrekte Schreibweise lautet also so:

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

Die internen Operationen von containsKey() und get() sind fast genau gleich. Sie müssen beide eine Hash-Suche durchführen, aber sie geben einfach zurück verschiedene Teile der Suchergebnisse. Mit anderen Worten: Wenn Sie es gemäß dieser „richtigen Schreibmethode“ schreiben, verursacht der einmalige Zugriff auf HashMap doppelte Kosten. Tassen!

C# verfügt über viele dieser detaillierten Designs, die rücksichtsvoller sind als Java. Sehen Sie, wie C# das Schlüsselwort out verwendet, um dieses Problem zu beheben.

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

Mit dieser Methode kann die C#-Version, die dem obigen Java-Code entspricht, wie folgt geschrieben werden:

// Dictionary<TKey, TValue> dict;
// TKey key;
TValue val;if (dict.TryGetValue(key, out val)) {
  // ...}

Dies ist Die Semantik von ContainsKey und Item[Key] wird kombiniert, um alle Informationen, die in einer Hash-Suche gefunden werden können, auf einmal zurückzugeben, wodurch der redundante Vorgang von „zwei Suchvorgängen“ aus der Quelle vermieden wird, was sich positiv auf die Leistung auswirkt Programm.

C#.net stellt ein Schlüsselwort params bereit. Nachdem ein Kollege einmal mehrere Versionen meiner überladenen Funktionen gesehen hatte, sagte er ruhig zu mir: „Ja, du kannst params verwenden.“ . Ich habe es später überprüft und jetzt habe ich alle vorherigen Versionen entfernt und es mithilfe von Parametern umgestaltet.

5 Paras

Anschließend werde ich über die Verwendung von Params und den Prozess sprechen, den ich durchlaufen habe.

5.1 Anforderungen des Problems
Auf der Clientseite ändern Kunden häufig die Abfragefelder. Vor ein paar Tagen gingen sie zum Server, um mehrere Modelle basierend auf vier Schlüsselfeldern abzufragen um ein weiteres Abfragefeld hinzuzufügen.

Abfragemethode basierend auf 4 Schlüsselfeldern:

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

        }

Die aufgerufene getPlansWithCondition-Methode ist

        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),带有这个参数的函数,只需要一个版本,这样解决了因为个数不一致而导致的多个重载版本,
在客户端调用时,将属性参数一一列数即可。

Das obige ist der detaillierte Inhalt von.NET Framework – Zusammenfassung des in, out, ref, paras verwendeten Codes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn