2

I am hoping that this is a simple question, and it's just my brain that is missing that final link. And if there is another q&a elsewhere, please point me there and close this... but I couldn't find it anywhere.

Here is the gist:

I have a class with a method with optional parameters, something along the lines of

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

So far, so good.

Now, I am going to instantiate the class and call the method in my code:

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

and that will work. If I provide optional parameters, it will still work.

But how do I handle a scenario, where I do not know if an optional value is actual provided. So for instance:

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

What if I do not know, if the optionalString1 and optionalString2 have a value or not? Do I then need to write an override for every scenario, along the lines of...

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

There has to be another way, and I bet it is simple and I am just having one of those Fridays... Is there something like...

Test.Method(requiredStrinig, if(!optionalString1.isEmpty())... 
4ndy
  • 550
  • 1
  • 9
  • 23
  • refer to [this](http://stackoverflow.com/questions/199761/how-can-you-use-optional-parameters-in-c) as it looks to be similar to your query. – fujiFX Apr 01 '16 at 00:52
  • Thank you, @fujiFX. I had a read of that one before, but it's not quite that. Imagine, I had a supplier field in a form, which is optional, but has a default value of "MySupplier". So, if I call the method without the supplier variable, it will work and populate that field in the database with "MySupplier". But, what if the supplier isn't filled out, and I pass "" to my method. It is then going to populate the field with "", which is wrong. It should be "MySupplier"... does that make sense? – 4ndy Apr 01 '16 at 00:57
  • IMO, if you need to know whether or not the default value was passed (the value was omitted in the call) then you should not be using optional parameters - they're for when a meaningful default value exist. – 500 - Internal Server Error Apr 01 '16 at 01:14

3 Answers3

4

You should invert the logic - have those optional parameters be null and then do checks in method. So in your case method should be something like:

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
}

Then calling that method will be easier in outside code and the logic within the method will be able to handle null cases. Outside of method you don't need to worry about those extra parameters, i.e. you can call the method any way you want, like:

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

Also as @Setsu said in comment you could do this to avoid passing null as second parameter:

Test.Method("required", opt2: "thanks @Setsu");
nikib3ro
  • 20,366
  • 24
  • 120
  • 181
-1

Use overloads instead, it gives you better semantics and in case you guess the parameters from client code you'd be sure what overload to use, besides, you'll have all the machinery in one place, check out this technique, hope this helps, regards.

class Program {

  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));         
  }

}

  • What if the caller only wants to supply `p3`? What if we want to extend the function with a new optional parameter `p4`? Your approach leads to code bloat pretty quickly and isn't how overloading should be used in C#. – Setsu Apr 01 '16 at 01:13
  • In the above example finite arguments are shown with no possibility to supress the call to the first argument, if infinite parameters were shown to be considered I would definitely provide a different solution, since I want to stick to the initial problem, I provide this technique. – Carlos Alberto Flores Onofre Apr 01 '16 at 01:19
  • I considered overloads, but I have methods with up to 80 parameters, so I'd have to write overloads for every single combination of available parameters... it would work, too, but it wasn't practical.Thank you, @CarlosAlbertoFloresOnofre – 4ndy Apr 01 '16 at 02:15
  • You are right ToshiBoy, however, in modern design, having 80 parameters is totally discouraged and since you sometimes are passing your parameters without knowing the values (you're passing them anyway) you don't have optional parameters actually, in fact you have optional values in those parameters which should be handled in your method. Robert C. Martin in "Clean code" encourages the use of three parameters as maximum, I understand your need here, so may be it'll be useful to use a data structure as a Dto to encapsulate your data. – Carlos Alberto Flores Onofre Apr 01 '16 at 17:04
-2

Optional parameters, are, well, optional. They seem to be a way to reduce the number of overloads you have for a method. If you receive all three parameters, you will have to decide if the second or third parameters are empty and need set to their "default" values.

My suggestion is you call your method with three strings and decide in the method if you have to change the values for string two and three. I would probably use a const or readonly instead of the default values.

Doug
  • 3,472
  • 3
  • 21
  • 18
  • Your suggestion would be wrong, and would defeat the entire reason optional parameters exist. If you *have* to call it with three strings and decide in the method whether they needed to be changed, you're not using optional parameters at all, because you still have to pass all three strings. – Ken White Apr 01 '16 at 01:04
  • Perhaps, it is, in your opinion. However, if you try to follow the concept of dependency injection, the calling method should not decide what the receiving method does with the data it receives. Optional parameters also change the interface of the method. method(param1) has a different signature than method(param1, param2=null, param3=null), so to me, it is of limited value unless you have a use case for it. I don't believe the OP has a valid use case for it. – Doug Apr 01 '16 at 01:08
  • You're absolutely correct. It is my opinion that you are 100% wrong, and that is why I downvoted your answer. That's precisely how this site works; when you're wrong, you get downvoted. – Ken White Apr 01 '16 at 01:09
  • 2
    That's not an opinion. It's a fact. If optional parameters are required, then they're no longer optional. – mason Apr 01 '16 at 01:09
  • @KenWhite, sorry, submitted the reply before adding my entire response, wasn't trying to say that you don't get to have your own opinion :) – Doug Apr 01 '16 at 01:13
  • None of the details you've provided in your comment appear in your answer. Does it appear that at this point the asker of this question needs to be concerned about dependency injection? The question didn't ask for suggestions for different approaches; it asks about using optional parameters. Answers should address that question. – Ken White Apr 01 '16 at 01:16
  • @mason, yes, I agree with you. However, if you are created two "optional" strings, why would you want to have logic in two places to decide what to do if the strings were empty or not? – Doug Apr 01 '16 at 01:18