可选参数以及参数数组

Mor*_*iya 5 c# arguments args optional-parameters ambiguous

我有一个日志记录接口,我使用一些有用的扩展方法对其进行了扩展,以便我可以传递格式和参数列表,以避免每次调用该方法时都必须使用字符串格式。(它还帮助我遵循 FXCops 文化信息规则)

所以我可以打电话:

logger.Debug("Created {0} with id {1}",typeof(MyObject).Name ,myObject.Id);
Run Code Online (Sandbox Code Playgroud)

代替:

logger.Debug(string.Format("Created {0} with id {1}", typeof(MyObject).Name, myObject.Id));
Run Code Online (Sandbox Code Playgroud)

我现在发现自己处于一个有点棘手的情况,因为在日志中获取一些关于日志记录位置的信息(例如文件、方法和行号)会非常有帮助。这可能与整齐的实现[CallerMemberName][CallerFilePath][CallerLineNumber]属性。

logger.Debug("Created {0} with id {1}", typeof(MyObject).Name, myObject.Id);
Run Code Online (Sandbox Code Playgroud)

然后会给我一个日志条目,例如:

“MyObjectProvider.cs,提供,第 50 行 | 创建的 MyObject,ID 为 1564”

这里的问题是方法签名看起来像这样:

public static void Debug(this ILogger logger, string format [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0, params object[] args)
Run Code Online (Sandbox Code Playgroud)

这是不可能的,因为[Caller*]属性使参数成为可选的,并且不适用于 args 参数。

我还尝试使用固定数量的字符串作为参数进行多个实现,如下所示:

public static void Debug(this ILogger logger, string format [CallerMemberName] string callerMemberName = "",string arg, string arg2 , ...etc... , [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
Run Code Online (Sandbox Code Playgroud)

但是后来我收到编译器错误,说“以下方法或属性之间的调用不明确”

我现在几乎已经放弃了这个问题,但我心里想,“也许 SO 可以为我找到解决方案”。所以这里是......是否可以同时使用params object[] args[CallerFilePath]以任何方式或者有另一种方式来获得预期的结果?

Luk*_*ley 1

您不能将两者组合在方法签名中。您可以做的是其中之一,然后传递null到您需要可选参数的地方,这对您有用吗?

Foo(s, null);
public void Foo(string s, params string[] sArray)
{

}

Foo(new string[] {""});
private static void Foo(string[] sArray,  string s = "")
{
}
Run Code Online (Sandbox Code Playgroud)

或者

为什么不使用一个处理格式的类并将其设为可选呢?

public class LogArgs
{
  private string _formatString;
  private string[] _args;
  public LogArgs(string formatString, params string[] args)
  {
    _formatString = formatString;
    _args = args;
  }
  public override string ToString()
  {
    return string.Format(_formatString, _args);
  }
}

public void Foo(string mandatory, LogArgs optionalParam = null)
{
  //Do Stuff
}

Foo("", new LogArgs("{0} is formatted", ""));
Run Code Online (Sandbox Code Playgroud)