为 C# 添加默认参数
一个小的代码生成器,

更新于 2007 年 12 月
- 构造函数重载支持
- 自动粘贴
- Linkify 集成
引言
开始学习 C# 时,最大的烦恼之一就是缺少默认参数。手动生成两三个重载是可以接受的,但看到 MessageBox
的 28 个重载,就让我头晕目眩(而且是难受的那种)。
现在我无法修改 C# 编译器以使其神奇地支持此功能。但我可以提供一个代码生成器,它可以从包含默认参数的声明中创建一组重载。
使用工具
在第一个编辑框中输入你的声明。你可以像在 C++ 中一样添加默认参数,生成的代码会立即显示在下面的文本字段中。单击“复制”将生成的代码复制到剪贴板。示例
void Add(string name = "(none)", int age = 22)
以上代码生成以下实现
// $overload: void Add(string name = "(none)", int age = 22){
// do your worst! - implement the actual method here
}
#region overloads for: Add
public void Add(string name)
{
Add(name, 22);
}
public void Add()
{
Add("(none)", 22);
}
#endregion // overloads
public void Add(string name, int age)
第一个重载是你实际实现的那个方法。其他重载的参数列表已缩减,并调用第一个方法。
第一行是用于与 Linkify 集成的(见下文)。
变得更好(可选)
C++ 默认参数允许省略参数列表末尾的参数。但是,在上面的示例中,当参数类型不同时,你可能希望省略名称但仍指定年龄。我添加了一个自定义“关键字”`optional`,它可以从参数列表的中间删除参数。
void Add(optional string name = "(none)", int age = 22)
这将生成以下签名
public void Add(string name, int age) { } // the one to implement
public void Add(string name)
public void Add()
public void Add(int age)
最后一个省略了 string name
参数。
确保生成的重载没有歧义是你的责任。如果你觉得无法胜任,编译器会捕获你!
与 Visual Studio 集成 - Linkify
我更新了我的 Linkify 文章,它允许从源代码注释中访问 URL 和运行外部工具。此外,DefaultOverloader
现在生成 Linkify 可以理解的声明行。
// $overload: void Add(string name = "(none)", int age = 22)
void Add(string name, int age)
注意:你需要在 Linkify 配置对话框中先设置 DefaultOverloader
可执行文件的路径。有关详细信息,请参阅该文章。
将光标放在“$overload
”上,然后单击“Linkify”。Default Overloader 会打开,并将你的声明已就位。
你也可以通过单击“copy head”分别复制两行声明,“copy body”复制重载区域。这允许保留主函数实现的函数体。自动粘贴使这一切变得更加容易。
自动粘贴
自动粘贴使这一切变得更加容易。它可以在没有安装 Linkify 的情况下工作(但那时,第一步会更复杂)。要修改现有的重载块
- 将光标放在“
$overload
”上,然后启动 Linkify
»DefaultOverloader
将打开,你的声明已准备好进行编辑。 - 进行修改后,单击“Auto-Paste”
»DefaultOverloader
最小化,并显示“Paste Head”作为标题 - 选择两行头部(注释和主函数头),然后粘贴
» 声明被新内容替换
»DefaultOverloader
(仍然最小化)显示“Paste Body”作为标题 - 折叠
#region Overloads for...
,选择整行,然后粘贴
» 新的重载替换了之前的重载
»DefaultOverloader
关闭
从最小化状态恢复 DefaultOverloader 以取消粘贴序列。第一个粘贴和第二个数据到达剪贴板之间有一个很小的延迟,所以不要连续粘贴得太快!
限制
解析器相当简单。所以你可能能够创建一些解释不正确的声明。一个问题是函数名带有多个模板参数:不要在模板列表中留空格,否则我将错误地识别函数名!
解析器不验证你的声明 - 这取决于你的编译器。
这不幸地不是默认参数的完整替代品。一些语言和 IDE 支持会很有帮助的一个方面是智能感知(Intellisense)——你仍然会单独列出所有重载。而且,当你修改声明时,你必须再次使用 Overloader。
争论
MSIL 或 C# 语言中没有默认参数是有原因的——要了解原因,请阅读 Eric Gunnersons 的回复 [^] 或者 在 Google 上搜索 [^]。
依我看,Eric 关于默认参数不在 MSIL 中的论点是站得住脚的——但这对 C# 语言本身并不适用。毕竟,C# 可以做我所做的。
关注点
布尔值的排列
为了实现 `optional` 关键字,我需要对包含它的所有变体进行排列。对于带有 `optional` 标记的 `N` 个参数,我需要生成 `N` 个布尔值的 `bool` 数组的所有可能组合。虽然网上可以找到一些方法,但没有一种对我来说是即插即用的。在思考如何自己实现它时,一个“后台线程”将 `bool` 数组的想法与 `bit` 数组联系了起来——`bool` 就是 `bit`!这允许一个非常简单的解决方案:只需从 `0` 数到 `2^N - 1`,并将每个位视为一个标志。
解析参数列表
源代码中包含一个(仍处于实验阶段的)分词器,它可以识别单引号和双引号字符串以及圆括号、方括号和花括号。这对于正确解析以下声明至关重要
SendMessage(string X = "Hello, World", int[,] targetCoords)
它几乎未经测试,需要一些扩展才能重用,但对于给定应用程序来说,它已经足够好用了。
谢谢
非常感谢所有在 C# 论坛上帮助过我的人——特别是 Judah Himango,他经常付出额外的努力。
我目前正在进行我的第一个 “真实世界” C# 项目(有时间压力、功能蔓延、宏伟计划,以及在每个人都试图分散你注意力时完成任务),你们在我克服这个难题(或者至少是“进入”这个难题)的过程中给予了极大的帮助。
历史
- 2007 年 4 月 21 日
- 首次上传
- 2007 年 4 月 23 日
- 修复了文章文本中的复制粘贴错误
- 2007 年 12 月 16 日
- 自动检测构造函数,并生成正确的重载
- 可以单独复制头部和重载体
- 自动粘贴,用于连续粘贴
- Linkify 集成(需要 2007 年 12 月版本!)