1.默认参数和可选参数,同扩展方法一样,一旦定义编译器就会在内部向该参数应用定制特性[DefaultParameterValue(value: object?)]
和[Optional]
,这些特性会在最终生成文件的元数据中持久性地存储下来。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class DefaultParameterValueAttribute : Attribute
{
public DefaultParameterValueAttribute(object? value)
{
this.Value = value;
}
// 默认值
public object? Value { get; }
}
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class OptionalAttribute : Attribute {}
}
2.CLR
允许以传引用而非传值的方式传递参数(传指针),所以C#
可以使用out
或ref
这类关键字。但是值得注意的是CLR
本身是不区分out
和ref
的,这也意味着无论用哪个关键字,都会生成相同的IL代码。
所以可以使用out或者ref来对方法进行重载,但是两者不能同时出现,因为在CLR中是相同的。
public class Class1{
public void GetValue(int x){}
public void GetValue(ref int x){}
}
public class Class2{
public void GetValue(int x){}
public void GetValue(out int x){}
}
/// <summary>
/// 不能同时使用ref和out 编译错误
/// </summary>
public class Class3{
public void GetValue(ref int x){}
public void GetValue(out int x){}
}
3.params
关键词支持向方法传递可变数量的参数,与其他关键字一样,编译器会应用[ParamArray]
特性。并且如果调用重载方法,会优先调用有匹配参数的方法。
namespace System
{
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public sealed class ParamArrayAttribute : Attribute
{
}
}
public class Foo
{
/// <summary>
/// Method1.
/// </summary>
/// <param name="paramInts"></param>
/// <returns></returns>
public int GetValue(params int[] paramInts)
{
int sum = 0;
if (paramInts!=null)
{
foreach (var i in paramInts)
{
sum += i;
}
}
return sum;
}
/// <summary>
/// Method2.
/// </summary>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <param name="arg3"></param>
/// <returns></returns>
public int GetValue(int arg1, int arg2, int arg3)
{
return arg1 + arg2 + arg3;
}
}
var foo = new Foo();
var result1 = foo.GetValue(1, 2, 3); // 调用Method2.
var result2 = foo.GetValue(1, 2, 3, 4, 5); // 调用Method1.