函数默认参数(C#)


大家都知道在C++中,我们可以为方法的参数指定一个默认值,像这样:

void foo(int i = 100);

当我们以这种形式调用方法的时候: foo(); 实际上参数i被赋于了默认值,所以相当于调用了foo(100);
然而在C#中是不支持参数的默认值的,那么如果我们要用到类似的功能应该怎么实现呢?考虑下面这个例子:

class Buffer
{
      public Buffer(int bufferSize = 100) //Compile Error
     {
            buf = new int [bufferSize];
      }
      private int[] buf;
}


首先当然要为Buffer提供一个无参的构造函数重载:
class Buffer
{
 
      public Buffer(int bufferSize)
     {
            buf = new int[bufferSize];
     }
      public Buffer():this(100)
     {
      }
      private int[] buf;
}    

但这个方法有一个问题就是我们把Buffer的默认大小hard-coding到了代码里,这有两个弊端,一是损害了代码的可读性,二是用以上方法,如果Buffer有多个重载的构造函数都用到bufferSize的默认值,一旦你要修改默认值的大小,不得不同时修改多处程序,一旦漏掉了其中的一个,说不定就麻烦大了。

所以,正确的方法是为bufferSize提供一个const的默认值:
class Buffer
{
      private const int defaultBufferSize = 100;
      public Buffer(int bufferSize)
     {
            buf = new int[bufferSize];
      }
      public Buffer():this(defaultBufferSize)
     {
     }
      private int[] buf;
}

观察编译器为public Buffer()产生的il代码

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       20 (0x14)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  ldarg.0
  IL_0007:  ldc.i4.s   100 //100即为defaultBufferSize的值
  IL_0009:  newarr     [mscorlib]System.Int32
  IL_000e:  stfld      int32[] Buffer::buf
  IL_0013:  ret
} // end of method Buffer::.ctor

defaultBufferSize的值在相应的调用处被替换成了字面常量(这其实也就是const成员的特性),所以使用defaultBufferSize不会影响public Buffer()的执行效率。而由于const成员隐含了static的特性,所以一个Buffer类只有一个defaultBufferSize的变量,性能的影响也是很小的。

我们可以看到.net 类库中的许多类都使用了这种方法
<think>嗯,用户想了解C#中带默认形参的函数。首先,我需要确认默认参数C#中的正确术语和版本支持。记得C# 4.0开始引入了命名参数和可选参数,这可能就是用户所指的。 接下来,应该解释什么是默认参数,也就是在方法定义时给参数默认值。调用时可以不传递这些参数编译器会自动使用默认值。需要举一个例子,比如一个带有两个参数的方法,其中第二个参数默认值。 然后,可能需要提到调用方式,包括位置参数和命名参数的混合使用。比如,可以跳过有默认值参数,或者用命名参数指定后面的参数。例如,Add(5)或者Add(y:10, x:5)这样的调用。 另外,需要注意默认参数的限制,比如必须是编译时常量,或者只能是某些类型的值。还有,默认参数必须放在参数列表的最后,不能放在非默认参数之前。否则会导致编译错误。 可能还需要比较一下C#和其他语言的区别,比如Python中的默认参数,或者C++中的类似功能,但这里用户可能不需要,所以保持重点在C#上。 用户可能想知道使用默认参数的好处,比如减少方法重载的数量,提高代码的可读性和维护性。这时候可以举一个例子,比如不需要写多个重载方法,只需要一个带有默认参数的方法即可。 同时,应该提醒用户一些注意事项,比如修改默认参数的值可能需要重新编译所有调用该方法的代码,否则可能保留旧的默认值。这点在版本更新时容易出问题,需要注意。 最后,总结一下默认参数的适用场景,比如参数有合理的默认值,或者方法经常以某些常用值被调用时,使用默认参数可以简化调用代码。同时,也要注意不要滥用,确保默认值确实符合大多数情况的需求,避免引入歧义或错误。 可能还需要检查一下是否有其他相关的内容,比如params关键字和默认参数的区别,或者可选参数和重载方法的选择依据。不过根据问题范围,可能不需要深入这些细节,除非用户后续提问。 现在需要把这些点组织成结构清晰的回答,分步骤介绍,并确保示例代码正确,符合C#语法。同时,要使用中文,保持语言流畅易懂。</think>在 C# 中,带默认形参的函数(又称**可选参数**)允许在方法定义时为参数指定默认值。当调用方法时,若未传递该参数,则自动使用默认值。以下是逐步解析: --- ### 一、基本语法 ```csharp // 定义方法时用 = 赋值默认值 public void PrintMessage(string message, int repeatCount = 1) { for (int i = 0; i < repeatCount; i++) { Console.WriteLine(message); } } ``` - `repeatCount` 是可选参数默认值为 `1` - 调用时可不传此参数:`PrintMessage("Hello");`(输出 1 次) - 也可显式传值:`PrintMessage("Hi", 3);`(输出 3 次) --- ### 二、调用规则 1. **位置参数优先** ```csharp PrintMessage("Test"); // 正确:使用默认 repeatCount=1 PrintMessage("Test", 2); // 正确:覆盖默认值 ``` 2. **命名参数跳过中间参数** ```csharp public void Example(int a = 1, int b = 2, int c = 3) { } Example(b: 5); // 等效于 Example(1, 5, 3) Example(c: 0, a: 10); // 等效于 Example(10, 2, 0) ``` --- ### 三、注意事项 1. **默认值必须是编译时常量** ```csharp // 合法 int defaultVal = 10; public void Func1(int x = 5 + 3) { } // 常量表达式 public void Func2(string s = "default") { } // 非法 public void Func3(int x = DateTime.Now.Hour) // 编译时无法确定 ``` 2. **必填参数在前,可选参数在后** ```csharp // 正确 public void MethodA(int x, int y = 0) { } // 错误:必填参数不能放在可选参数后 public void MethodB(int x = 0, int y) { } ``` --- ### 四、与重载方法的对比 默认参数可减少冗余方法定义: ```csharp // 使用默认参数替代重载 public void Save(string path, bool overwrite = false) { } // 等效的重载写法 public void Save(string path) => Save(path, false); public void Save(string path, bool overwrite) { } ``` --- ### 五、适用场景 1. 参数有合理的默认行为(如日志记录级别默认为 `Info`) 2. 简化高频调用(如 `Connect(timeout: 5000)` 大部分时间无需指定) 3. 向后兼容时新增参数(避免破坏旧代码) --- ### 六、示例:复合使用 ```csharp public void DrawCircle( int radius, string color = "red", bool fill = false ) { } // 调用方式 DrawCircle(10); // color="red", fill=false DrawCircle(5, fill: true); // color="red", fill=true DrawCircle(3, "blue"); // fill=false ``` 通过合理使用默认参数,可提升代码简洁性和灵活性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值