“三元”运算符用于不同的方法签名

时间:2011-07-01 22:38:40

标签: c#

我正在寻找一种优雅的方法来选择方法签名(重载)并根据条件传递参数。我有一个导入器,它将生成要导入的最新文件,或者为数据采用显式路径。

目前我的代码如下:

if (string.IsNullOrEmpty(arguments.File))
{
    importer.StartImport();
}
else
{
    importer.StartImport(arguments.File);
}

我希望它看起来像这样(或概念上类似):

importer.StartImport(string.IsNullOrEmpty(arguments.File) ? Nothing : arguments.File);

这个想法是调用不同的方法签名。一些规定:

1)我不会依赖'null'来表示一个未指定的文件(即除了null之外的任何东西) 2)我不会将arguments struct传递给importer类;这违反了单一责任原则。

我知道的一个解决方案是只有一个StartImport()方法接受一个字符串,此时该方法解析条件并选择如何继续。我现在选择避免使用此解决方案,因为它只将if语句从一个方法移动到另一个方法。我问这个问题是因为:

1)我想将“8行”代码减少到1 2)如果C#能够做到这样的话,我真的很好奇。

6 个答案:

答案 0 :(得分:3)

  

我想将“8行”代码减少为1。

我认为你问的是错误的问题。这不是你拥有多少行代码,而是它们的清晰度,可维护性和可调试性。根据您的描述,从默认位置导入并使用已知文件导入语义不同 - 所以我认为您将它们分成两个不同的重载是正确的。事实上,您可能希望更进一步,实际上以不同的方式命名以进一步澄清差异。

  

如果C#能够做到这样的话,我真的很好奇。

当然,我们可以使用各种花哨的语言技巧来使它更紧凑......但我认为它们不会使代码更清晰。例如:

// build a Action delegate based on the argument...
Action importAction = string.IsNullOrEmpty(arguments.File) 
                            ? () => importer.StartImport() 
                            : () => importer.StartImport(arguments.File)
importAction(); // invoke the delegate...

上面的代码使用lambda + closure来创建正确类型的Action委托,然后调用该委托。但这几乎不太清楚......它的效率也略低,因为它需要创建一个委托,然后通过该委托调用该方法。在大多数情况下,性能开销完全可以忽略不计。这里真正的问题是使用闭包 - 使用闭包很容易误用代码 - 使用introduce bugs完全可以closures incorrectly

答案 1 :(得分:1)

你为什么不能这样做:

string.IsNullOrEmpty(arguments.File) ? importer.StartImport() : importer.StartImport(arguments.File));

答案 2 :(得分:1)

你不能使用'强类型'C#来做到这一点。重载解析在编译时执行:编译器将计算参数的静态(编译时)类型,并基于此解析。如果要使用两种不同的重载之一,则必须执行两次不同的调用。

在某些情况下,您可以使用dynamic类型将重载决策推迟到运行时。但是,这具有性能(和清晰度!)成本,并且在您的情况下不起作用,因为在这两种情况下需要传递不同数量的参数。

答案 3 :(得分:1)

是的,有可能(使用反射)。但我根本不会推荐它,因为你的代码比以前更多。你拥有的“8行”非常简单易读。使用反射的“单线”不是。但为了完整起见,这里有一个单行:

importer.GetType().GetMethod("StartImport", string.IsNullOrEmpty(arguments.File) ? new Type[0] : new Type[] { typeof(string) }).Invoke(importer, string.IsNullOrEmpty(arguments.File) ? new object[0] : new object[] { arguments.File) }));

答案 4 :(得分:0)

坦率地说,我认为如果将重载方法组合回单个方法并将条件移入其中而不是让调用者预先验证输入,那么您的代码将更具可读性和模块性。

importer.StartImport(arguments.File);

void StartImport(string File) {
  if (string.isNullOrEmpty(File)) {
      ...
  }
  else {
      ...
  }
}

假设您从代码中的多个位置调用该方法,您没有使用此方法分散违反DRY原则的条件OR三元表达式。

答案 5 :(得分:0)

.Value