首页 > 解决方案 > {CallerMemberName} 类似于 nameof() 参数的功能

问题描述

我正在编写更多的库代码并遇到了烦恼 - 这是一个示例

public static TParam RequiredParam<TParam>(TParam param, string name) where TParam : class 
{
  return param ?? throw new ArgumentNullException(name);
}

private readonly int _testInt;

public TestClass(int testInt)
{
  _testInt = RequiredParam(testInt, nameof(testInt));
}

基本上我必须在使用中传递名称

我想要的是:

public static TParam RequiredParam<TParam>(TParam param) where TParam : class 
{
  return param ?? throw new ArgumentNullException(*NAME STILL GETS HERE SOMEHOW*);
}

private readonly int _testInt;

public TestClass(int testInt)
{
  _testInt = RequiredParam(testInt);
}

有没有更好的办法?在 WPF 时代,我曾经像这样使用 [CallerMemberName]:

private void PropertyChanged([CallerMemberName]string name = default)
{
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

有谁知道类似的东西可以为此达到相同的结果?考虑到这个库被调用的频率,我不介意进入后期构建步骤或其他任何步骤,但出于性能原因,我更愿意避免反射。

编辑 - 让我的目标更清晰

标签: c#.netattributesmethod-signature

解决方案


首先,我个人无论如何都不会这样做,您将逻辑隐藏在另一种方法后面以节省几次击键。在这样做时,对于新读者来说,他们将不得不点击查看它的作用,而且你仍然必须使用它nameof

您可能可以通过反思来做一些事情,但即便如此,为了获得可疑的收益,它也会做很多工作。

我可以建议第三种方法吗?

为什么不为关键字创建一个 Resharper 模板args[tab]

$NAME$ = $NAME$ ?? throw new ArgumentNullException(nameof($NAME$));

好处是

  • 新读者可以很容易地看到发生了什么。
  • 您只有最少的击键次数,因为它会在几个字母后提示类型
  • 您节省了一些 IL 和对堆栈的调用

此外,如果您使用 Resharper,请查看代码注释属性


我猜你也可以使用一个表达式

例子

public void ExampleFunction(Expression<Func<string, string>> f) {
    Console.WriteLine((f.Body as MemberExpression).Member.Name);
}

用法

ExampleFunction(x => WhatIsMyName);

仍然在我看来,什么都没有真正得到


推荐阅读