在C#中强制命名参数

Use*_*rol 34 .net c# named-parameters c#-4.0

C#4引入了一个名为命名参数的特性,这在像这样的场景中特别有用

int RegisterUser(string nameFirst, string nameLast, string nameMiddle, string email)
Run Code Online (Sandbox Code Playgroud)

有没有办法强制使用命名参数?也许某些属性适用于我不知道的方法或编译器开关?我想可以使用代码检查器工具完成,但只想知道是否还有其他方法.

PS

对于那些感兴趣的人为什么可能需要它,为什么不使用类/结构来利用对象初始化器,有些情况是不可能的.就像调用不在您控制中的库或您必须遵守的奇怪代码约定一样.

use*_*855 27

可以强制调用者始终使用命名args.我不会在大多数情况下这样做,因为它相当丑陋,但这取决于需要多么安全的方法使用.

这是解决方案:

    int RegisterUser(
#if DEBUG
      int _ = 0,
#endif
      string nameFirst = null,
      string nameLast = null,
      string nameMiddle = null,
      string email = null) { /*...*/ }
Run Code Online (Sandbox Code Playgroud)

第一个参数是一个不应该使用的虚拟参数(并且为了提高效率而在Release中编译).但是,它确保必须命名所有后续参数.

有效用法是指定参数的任意组合:

    RegisterUser();
    RegisterUser(nameFirst: "Joe");
    RegisterUser(nameFirst: "Joe", nameLast: "Smith");
    RegisterUser(email: "joe.smith@example.com");
Run Code Online (Sandbox Code Playgroud)

尝试使用位置参数时,代码将无法编译.

  • 丑陋但聪明. (15认同)
  • 结果是,未使用的带有默认值的"_"参数强制其余的后续参数具有默认值,并在调用时进行命名. (4认同)
  • 使用您的编译器预处理器指令,如果未定义DEBUG符号,它就好像`int _ = 0`甚至不存在,因此它对发布版本没有任何影响......我不知道认为这个答案符合你的想法...... (2认同)

dri*_*iis 26

不,不是用C#语言.如果提供了所有参数,它将始终接受位置参数.

您可以构建自定义FxCop规则StyleCop规则来强制执行此操作 - 正如评论中所指出的,它可能是您感兴趣的StyleCop规则(感谢Kris).

  • 您不能制定自定义FxCop规则,因为FxCop规则适用于二进制文件,而不是源代码,并且命名参数被"编译掉".我想你可以制作一个自定义的StyleCop规则. (7认同)
  • 不,至于命名参数是PDB:"计算机说没有!". (2认同)

Nik*_*Nik 5

对不起一个无耻的插头!
我实现了一个Roslyn 分析器来强制使用一个方法的命名参数。

因此,如果您安装 RequireNamedArgs 分析器并在应使用命名参数调用的方法之前添加特殊注释:

//[RequireNamedArgs]
int RegisterUser(string nameFirst, string nameLast, string nameMiddle, string email)
Run Code Online (Sandbox Code Playgroud)

如果调用者尝试使用位置参数而不是命名参数,分析器将发出错误。

看看它的实际效果: 在此处输入图片说明

如果你决定试一试——这样做的风险由你自己承担:)