class Program { private static int s_n = 0; private static void M(int x = 9, string s = "A", DateTime dt = default(DateTime), Guid guid = new Guid()) { Console.WriteLine("x={0},s={1},dt={2},guid={3}", x, s, dt, guid); } public static void Main() { //1.等同于M(9,"A",default(DateTime),new Guid()); M(); //2.等同于M(8,"X",default(DateTime),new Guid()); M(8, "X"); //3.等同于M(5,"A",DateTime.Now,Guid.NewGuid()); M(5, guid: Guid.NewGuid(), dt: DateTime.Now); //4.等同于M(0,"1",default(DateTime),new Guid()); M(s_n++, s_n++.ToString()); //5.等同于以下两行代码: //string t1="2";int t2=3; //M(t2,t1,default(DateTime),new Guid()); M(s: (s_n++).ToString(), x: s_n++); } }
können Methoden, Konstruktormethoden und parametrisierte Eigenschaften (C#-Indexer) Parameter sein Geben Sie Standardwerte an. Sie können auch Standardwerte für Parameter angeben, die Teil der Delegatendefinition sind.
Parameter mit Standardwerten müssen nach allen Parametern ohne Standardwerte platziert werden. Es gibt jedoch eine Ausnahme: Parameter wie „Parameter-Array“ müssen nach allen Parametern (einschließlich denen mit Standardwerten) platziert werden, und das Array selbst darf keinen Standardwert haben.
Der Standardwert muss ein konstanter Wert sein, der zur Kompilierungszeit bestimmt werden kann (einschließlich primitiver Typen, Aufzählungstypen und aller Referenztypen, die auf Null gesetzt werden können). Ein Parameter eines Werttyps legt den Standardwert auf eine Instanz des Werttyps fest und bewirkt, dass alle seine Felder Nullwerte enthalten. Sie können die Schlüsselwörter default oder new verwenden, um diese Bedeutung auszudrücken. Der von den beiden Syntaxen generierte IL-Code ist genau derselbe.
Parametervariablen nicht umbenennen, da sonst jeder Aufrufer, der tatsächliche Parameter anhand des Parameternamens übergibt, auch seinen Code ändern muss.
Das Ändern des Standardwerts eines Parameters ist potenziell gefährlich , wenn die Methode von außerhalb des Moduls aufgerufen wird. Die Anrufstelle (wo der Anruf getätigt wird) bettet Standardwerte in ihre Anrufe ein. Wenn Sie später den Standardwert des Parameters ändern, aber den Code mit der Aufrufstelle nicht neu kompilieren, wird beim Aufruf Ihrer Methode der alte Standardwert übergeben. Erwägen Sie die Verwendung des Standardwerts 0/null als Sentinel-Wert , um das Standardverhalten anzuzeigen. Beispiel:
//不要这样做: private static string MakePath(string filename = "Untitled") { return string.Format(@"c\{0}.txt", filename); } //而要这样做: private static string MakePath(string filename = null) { return string.Format(@"C:\{0}.txt", filename ?? "Untitled"); }
Wenn der Parameter mit dem Schlüsselwort ref oder out markiert ist, kann der Standardwert nicht festgelegt werden.
Beachten Sie beim Aufruf einer Methode mit optionalen oder benannten Parametern die folgenden zusätzlichen Regeln und Prinzipien:
Die tatsächlichen Parameter können in sein jede Reihenfolge bestanden, , aber benannte Argumente können nur am Ende der Argumentliste erscheinen.
Parameter ohne Standardwerte können nach Namen übergeben werden, aber alle erforderlichen Argumente müssen übergeben werden (entweder nach Position oder nach Namen).
c# lässt nicht zu, dass die tatsächlichen Parameter zwischen Kommas wie M(1,,DateTime.Now)
weglassen. Wenn Sie bei Parametern mit Standardwerten deren tatsächliche Parameter weglassen möchten, übergeben Sie einfach die tatsächlichen Parameter, indem Sie den Parameternamen übergeben.
Wenn der Parameter ref/out erfordert, verwenden Sie bitte die folgende Syntax, um den tatsächlichen Parameter durch Übergabe des Parameternamens zu übergeben:
//方法声明: private static void M(ref int x) { ...} //方法调用: int a = 5; M(x: ref a);
Wenn C# eine COM-Komponente aufruft und tatsächliche Parameter als Referenz übergeben werden, erlaubt C# auch das Weglassen von ref/out, um die Codierung weiter zu vereinfachen. Wenn der Anruf jedoch keine COM -Komponente ist, verlangt C#, dass der Ref/Out -Schlüsselwort auf die tatsächlichen Parameter angewendet werden muss.
Var kann nicht zum Deklarieren des Methodenparametertyps verwendet werden.
Sie können VAR nicht verwenden, um Felder in einem Typ zu deklarieren.
verwechseln Sie dynamisch nicht mit var . Das Deklarieren lokaler Variablen mit var ist lediglich eine vereinfachte Syntax, die erfordert, dass der Compiler den spezifischen Datentyp basierend auf dem Ausdruck ableitet. Das Schlüsselwort var kann nur lokale Variablen innerhalb einer Methode deklarieren, während das Schlüsselwort dynamic für lokale Variablen, Felder und Parameter gilt. Der Ausdruck kann nicht in var konvertiert werden, kann jedoch in dynamisch konvertiert werden. Mit var deklarierte Variablen müssen explizit initialisiert werden, mit dynamic deklarierte Variablen müssen jedoch nicht initialisiert werden.
private static void ImplicitlyTypedLocalVariables() { var name = "Jeff"; ShowVariableType(name); //显示:System.String //var n=null; //错误,不能将null赋给隐式类型的局部变量 var x = (String)null; //可以这样写,但意义不大 ShowVariableType(x); //显示:System.String var numbers = new int[] { 1, 2, 3, 4 }; ShowVariableType(numbers); //显示:System.Int32[] //复杂类型能少打一些字 var collection = new Dictionary<String, Single>() { { "Grant", 4.0f } }; //显示:System.Collections.Generic.Dictionary`2[System.String,System.Single] ShowVariableType(collection); foreach (var item in collection) { //显示:System.Collections.Generic.KeyValuePair`2[System.String,System.Single] ShowVariableType(item); } } private static void ShowVariableType<T>(T t) { Console.WriteLine(typeof(T)); }
CLR übergibt standardmäßig alle Methodenparameter als Wert.
CLR ermöglicht es, Parameter eher mit Referenz als durch Wert zu übergeben. C# unterstützt diese Funktionalität anhand der Schlüsselwörter out oder ref .
CLR unterscheidet nicht zwischen out und ref, und unabhängig davon, welches Schlüsselwort verwendet wird, wird derselbe IL-Code generiert. Darüber hinaus sind die Metadaten fast identisch, bis auf ein Bit, mit dem aufgezeichnet wird, ob bei der Deklaration der Methode out oder ref angegeben wurde.
Der C#-Compiler behandelt diese beiden Schlüsselwörter unterschiedlich, und dieser Unterschied bestimmt, welche Methode für die Initialisierung des referenzierten Objekts verantwortlich ist.
Die Methode, die out zum Markieren des Parameters verwendet, kann den Wert des Parameters nicht lesen und muss vor der Rückgabe auf diesen Wert schreiben. Wenn eine Methode hingegen mit ref markiert ist, muss der Wert des Parameters vor dem Aufruf der Methode initialisiert werden. Die aufgerufene Methode kann den Wert lesen und/oder auf den Wert
< schreiben 🎜>public static void Main() { int x; //x没有初始化 GetVal(out x); //x不必初始化 Console.WriteLine(x); //显示“10” } private static void GetVal(out int v) { v = 10; //该方法必须初始化v }
public static void Main() { int x = 5; //x已经初始化 GetVal(ref x); //x必须初始化 Console.WriteLine(x); //显示“15” } private static void GetVal(ref int v) { v += 10; //该方法可使用v的已初始化的值 }
public static void Main() { string s1 = "Jeffrey"; string s2 = "Richter"; //错误!错误!错误! //Swap(ref s1, ref s2); //以传引用的方式传递的变量, //必须和方法预期的匹配 object o1 = s1, o2 = s2; Swap(ref o1,ref o2); //完事后再将object转型为string s1 = (string)o1; s2 = (string)o2; Console.WriteLine(s1); //显示“Richter” Console.WriteLine(s2); //显示“Jeffrey” } private static void Swap(ref object a, ref object b) { object t = b; b = a; a = t; }
public static void Main() { string s1 = "Jeffrey"; string s2 = "Richter"; Swap(ref s1, ref s2); Console.WriteLine(s1); //显示“Richter” Console.WriteLine(s2); //显示“Jeffrey” } private static void Swap<T>(ref T a, ref T b) { T t = b; b = a; a = t; }
params 只能应用于方法签名中的最后一个参数。
这个参数只能标识一维数组(任意类型)。
可为这个参数传递 null 值,或传递对包含零个元素的一个数组的引用。
调用参数数量可变的方法对性能有所影响(除非显式传递null)。要减少对性能的影响,可考虑定义几个没有使用 params 关键字的重载版本,如System.String
类的Concat方法。
public static void Main() { Console.WriteLine(Add(new int[] { 1, 2, 3, 4, 5 }));//显示“15” //或 Console.WriteLine(Add(1, 2, 3, 4, 5)); //显示“15” //以下两行都显示“0” Console.WriteLine(Add()); //向Add传递 new int[0] Console.WriteLine(Add(null)); //向Add传递 null :更高效(因为不会分配数组) } private static int Add(params int[] values) { // 注意:如果愿意,可将values数组传给其他方法 int sum = 0; if (values != null) { for (int x = 0; x < values.Length; x++) sum += values[x]; } return sum; }
声明方法的参数类型时,应尽量指定最弱的类型,宁愿要接口也不要基类。例如,如果要写方法来处理一组数据项,最好是用接口(比如 IEnumerable<T>
)声明参数,而不要用强数据类型(比如List<T>
)或者更强的接口类型(比如ICollection<T>
或IList<T>
):
//好:方法使用弱参数类型 public void ManipulateItems<T>(IEnumerable<T> collection){} //不好:方法使用强参数类型 public void ManipulateItems<T>(List<T> collection) { }
相反,一般最好是将方法的返回类型声明为最强的类型(防止受限于特定类型)。例如,方法最好返回FileStream而不是Stream对象:
//好:方法使用强返回类 public FileStream OpenFile() { } //不好:方法使用弱返回类 public Stream OpenFile() { }
如果想保持一定的灵活性,在将来更改方法返回的东西,请选择一个较弱的返回类型。
//灵活:方法使用较弱的返回类型 public IList<string> GetStringCollection() { } //不灵活:方法使用较强的返回类型 public List<string> GetStringCollection() { }
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung optionaler Parameter und Beispiele benannter Parameter. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!