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++); } }
기본값은 메서드의 매개변수, 생성자 메서드 및 매개변수화된 속성(C# 인덱서)에 대해 지정할 수 있습니다. 위임 정의의 일부인 매개변수에 대한 기본값을 지정할 수도 있습니다.
기본값이 있는 매개변수는 기본값이 없는 모든 매개변수 뒤에 배치되어야 합니다. 그러나 한 가지 예외가 있습니다. "매개변수 배열"과 같은 매개변수는 모든 매개변수(기본값이 있는 매개변수 포함) 뒤에 배치되어야 하며 배열 자체는 기본값을 가질 수 없습니다.
기본값은 컴파일 타임에 결정될 수 있는 상수 값이어야 합니다(기본 유형, 열거 유형 및 null로 설정될 수 있는 모든 참조 유형 포함). 값 유형의 매개변수는 기본값을 값 유형의 인스턴스로 설정하고 해당 필드의 모든 값이 0이 되도록 합니다. default 또는 new 키워드를 사용하여 이 의미를 표현할 수 있습니다. 두 구문으로 생성된 IL 코드는 완전히 동일합니다.
매개변수 변수의 이름을 바꾸지 마세요. 그렇지 않으면 매개변수 이름으로 실제 매개변수를 전달하는 호출자도 코드를 수정해야 합니다.
메서드가 모듈 외부에서 호출되는 경우 매개변수의 기본값을 변경하는 것은 잠재적으로 위험할 수 있습니다. 호출 사이트(호출이 이루어지는 곳)는 호출에 기본값을 포함합니다. 나중에 매개변수의 기본값을 변경했지만 호출 사이트가 포함된 코드를 다시 컴파일하지 않으면 메서드를 호출할 때 이전 기본값이 전달됩니다. 기본 동작을 나타내기 위해 기본값 0/null을 센티널 값으로 사용하는 것을 고려하세요. 예:
//不要这样做: 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"); }
매개변수에 ref 또는 out 키워드가 표시되면 기본값을 설정할 수 없습니다.
선택적 또는 명명된 매개변수가 있는 메서드를 호출할 때 다음 추가 규칙과 원칙에도 주의하세요.
실제 매개변수는 순서에 관계없이 전달될 수 있습니다. 그러나 명명된 실제 매개변수는 실제 매개변수 목록 끝 .
기본값이 없는 매개변수는 이름으로 전달될 수 있지만 모든 필수 인수는 위치 또는 이름으로 전달되어야 합니다.
C#에서는 M(1,,DateTime.Now)
와 같이 쉼표 사이에 실제 매개변수를 생략하는 것이 허용되지 않습니다. 기본값이 있는 매개변수의 경우 실제 매개변수를 생략하려면 매개변수 이름을 전달하여 실제 매개변수를 전달하면 됩니다.
매개변수에 ref/out이 필요한 경우 매개변수 이름을 전달하여 실제 매개변수를 전달하려면 다음 구문을 사용하세요.
//方法声明: private static void M(ref int x) { ...} //方法调用: int a = 5; M(x: ref a);
C#에서 COM 구성 요소를 호출할 때 reference 실제 매개변수를 전달할 때 C#에서는 ref/out을 생략할 수 있으므로 코딩이 더욱 단순화됩니다. 그러나 호출이 COM 구성 요소가 아닌 경우 C#에서는 ref/out 키워드를 실제 매개 변수에 적용해야 합니다.
var를 사용하여 메서드의 매개 변수 유형을 선언할 수 없습니다.
var를 사용하여 유형의 필드를 선언할 수 없습니다.
dynamic과 var을 혼동하지 마세요. var을 사용하여 지역 변수를 선언하는 것은 컴파일러가 표현식을 기반으로 특정 데이터 유형을 유추하도록 요구하는 단순화된 구문일 뿐입니다. var 키워드는 메서드 내에서 지역 변수만 선언할 수 있는 반면, dynamic 키워드는 지역 변수, 필드 및 매개변수에 적용됩니다. 표현식은 var 로 변환할 수 없지만 dynamic 으로 변환할 수 있습니다. var로 선언된 변수는 명시적으로 초기화되어야 하지만 dynamic로 선언된 변수는 초기화할 필요가 없습니다.
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은 기본값으로 값으로 전달되는 모든 메서드 매개변수를 사용합니다.
CLR을 사용하면 매개변수를 값이 아닌 참조로 전달할 수 있습니다. C#에서는 out 또는 ref 키워드를 사용하여 이 기능을 지원합니다.
CLR은 out과 ref을 구분하지 않으므로 어떤 키워드를 사용하더라도 동일한 IL 코드가 생성됩니다. 또한 메소드 선언 시 out 또는 ref 지정 여부를 기록하는 데 사용되는 1비트를 제외하면 메타데이터는 거의 동일합니다.
C# 컴파일러는 이 두 키워드를 다르게 처리하며, 이 차이점에 따라 참조된 개체 초기화를 담당하는 메서드가 결정됩니다.
매개변수를 표시하기 위해 out을 사용하는 메서드는 매개변수의 값을 읽을 수 없으며 반환하기 전에 이 값에 써야 합니다. 반대로 메소드를 ref로 표시하면 메소드를 호출하기 전에 매개변수 값을 초기화해야 합니다. 호출된 메소드는 값을 읽거나 값에 를 쓸 수 있습니다. ref와 out만 다른 오버로드된 메서드.
참조로 메서드에 전달된 변수는 메서드 서명에 선언된 유형과 동일한 유형이어야 합니다. 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() { 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() { }
위 내용은 선택적 매개변수 및 명명된 매개변수 예에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!