【问题标题】:C# not passing parameters if those parameters are optional如果这些参数是可选的,则 C# 不传递参数
【发布时间】:2016-04-01 00:43:37
【问题描述】:

我希望这是一个简单的问题,只是我的大脑缺少最后一个链接。如果其他地方还有其他问答,请指点我那里并关闭它……但我在任何地方都找不到。

这里是要点:

我有一个带有可选参数的方法的类,类似于

public class Test
{
    public void Method(string required, string someoptionalparameter="sometext", string anotheroptionalparameter="someothertext")
    {
        // do something here with the parameters
    }
 }

到目前为止,一切都很好。

现在,我将实例化该类并在我的代码中调用该方法:

 ...
Test.Method("RequiredString");

这将起作用。如果我提供可选参数,它仍然可以工作。

但是我如何处理一个我不知道是否实际提供了可选值的场景。比如:

...
Test.Method(requiredString,optionalString1,optionalString2);
...

如果我知道 optionalString1 和 optionalString2 是否有值怎么办?然后我是否需要为每个场景编写一个覆盖,沿着......

if (optionalString1.isEmpty() && optionalString2.isEmpty())
{
     Test.Method(requiredString);
}
else if ((!optionalString1.isEmpty() && optionalString2.isEmpty())
{
     Test.Method(requiredString, optionalString1);
}
else if...

必须有另一种方式,我敢打赌这很简单,我只是有一个星期五......有没有类似......

Test.Method(requiredStrinig, if(!optionalString1.isEmpty())... 

【问题讨论】:

  • 参考this,因为它看起来与您的查询相似。
  • 谢谢@fujiFX。我以前读过那本书,但并不完全如此。想象一下,我在表单中有一个供应商字段,它是可选的,但默认值为“MySupplier”。因此,如果我在没有供应商变量的情况下调用该方法,它将起作用并使用“MySupplier”填充数据库中的该字段。但是,如果没有填写供应商怎么办,我将“”传递给我的方法。然后它将用“”填充该字段,这是错误的。应该是“MySupplier”……这有意义吗?
  • IMO,如果您需要知道是否传递了默认值(调用中省略了该值),那么您不应该使用可选参数 - 它们用于有意义的默认值存在。

标签: c#


【解决方案1】:

你应该颠倒逻辑 - 让那些可选参数为空,然后检查方法。所以在你的情况下,方法应该是这样的:

public void Method(string required, string opt1 = null, string opt2 = null)
{
    opt1 = opt1 ?? "some default non-null value if you need it";
    opt2 = opt2 ?? "another default value, this one for opt2";

    // for those not knowing what it does ?? is basically 
    // if (opt1 == null) { opt1 = "value"; }

    //... rest of method
}

然后在外部代码中调用该方法将更容易,并且方法内的逻辑将能够处理空情况。在方法之外,您无需担心那些额外的参数,即您可以以任何方式调用该方法,例如:

Test.Method(requiredString);
Test.Method(requiredString, "something");
Test.Method(requiredString, null, "something else");

正如@Setsu 在评论中所说,您可以这样做以避免将 null 作为第二个参数传递:

Test.Method("required", opt2: "thanks @Setsu");

【讨论】:

  • 您可以使用命名参数来避免调用代码中的第二个空参数
  • 太棒了,谢谢@kape123 和@Setsu!这就是我的想法。
【解决方案2】:

改为使用重载,它可以为您提供更好的语义,并且如果您从客户端代码中猜测参数,您可以确定要使用什么重载,此外,您会将所有机器放在一个地方,请查看此技术,希望这会有所帮助,问候。

类程序{

  static void Main(string[] args) {
     Work("Hi!");
  }

  private static void Work(String p1) {
     Work(p1, null, null);
  }

  private static void Work(String p1, String p2) {
     Work(p1, p2, null);
  }

  private static void Work(String p1, String p2, String p3) {         
     if ( String.IsNullOrWhiteSpace(p2) ) p2 = String.Empty;
     if ( String.IsNullOrWhiteSpace(p3) ) p3 = String.Empty;

     Console.WriteLine(String.Concat(p1, p2, p3));         
  }

}

【讨论】:

  • 如果调用者只想提供p3怎么办?如果我们想用一个新的可选参数p4 来扩展函数呢?您的方法很快导致代码膨胀,而不是在 C# 中应该如何使用重载。
  • 在上面的例子中,有限参数显示不可能抑制对第一个参数的调用,如果显示无限参数被考虑,我肯定会提供不同的解决方案,因为我想坚持最初的问题,我提供了这种技术。
  • 我考虑过重载,但我有多达 80 个参数的方法,所以我必须为可用参数的每个组合编写重载......它也可以工作,但它不是t 实用。谢谢你,@CarlosAlbertoFloresOnofre
  • 你是对的 ToshiBoy,然而,在现代设计中,完全不鼓励使用 80 个参数,因为有时你在不知道值的情况下传递参数(无论如何你都在传递它们)你没有可选参数实际上,实际上您在那些应该在您的方法中处理的参数中有可选值。 Robert C. Martin 在“清洁代码”中鼓励最多使用三个参数,我理解您的需求,因此使用数据结构作为 Dto 来封装您的数据可能会很有用。
【解决方案3】:

可选参数,嗯,是可选的。它们似乎是一种减少方法重载次数的方法。如果您收到所有三个参数,则必须确定第二个或第三个参数是否为空,并且需要设置为它们的“默认”值。

我的建议是你用三个字符串调用你的方法,并在方法中决定是否必须更改字符串 2 和 3 的值。我可能会使用 const 或 readonly 而不是默认值。

【讨论】:

  • 您的建议是错误的,并且会破坏可选参数存在的全部原因。如果您必须用三个字符串调用它并在方法中决定是否需要更改它们,那么您根本没有使用可选参数,因为您仍然需要传递所有三个字符串。跨度>
  • 也许,在你看来是这样。但是,如果您尝试遵循依赖注入的概念,则调用方法不应决定接收方法如何处理其接收到的数据。可选参数也会改变方法的接口。 method(param1) 与 method(param1, param2=null, param3=null) 有不同的签名,所以对我来说,除非你有用例,否则它的价值是有限的。我不相信 OP 有一个有效的用例。
  • 你是绝对正确的。我认为您是 100% 错误的,这就是为什么我对您的回答投了反对票。这正是该网站的运作方式;当你错了,你就会被否决。
  • 这不是意见。这是事实。如果需要可选参数,则它们不再是可选的。
  • @KenWhite,抱歉,在添加我的整个回复之前提交了回复,并不是说你没有自己的意见:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
相关资源
最近更新 更多