vendredi 23 février 2018

Instruct constructor method to use default value if null

I'm designing an API wrapper with a constructor something like this:

public class Client(string username, string password, int timeout = 60)

The caller looks like this:

class Program 
{
    private static int? Timeout => GetFromConfig("Timeout");

    static void Main(string[] args)
    {
        Client client = new Client(Username, Password, Timeout);
        // do things...
    }
}

I would like to use Client's default timeout (60) if Timeout is null.

I know of a few options:

1) Use conditional logic in Main

static void Main(string[] args)
{
    if (Timeout == null) 
    {
        Client client = new Client(Username, Password);
    }
    else 
    {
        Client client = new Client(Username, Password, Timeout);
    }
}

I dislike this solution because 1) it's a lot of code, and 2) the code grows exponentially as I add conditional parameters (e.g. if I added int MaxFailedRequests = 5 to Client()'s signature, my if/else block grows to 4 blocks).

2) Handle null values in Client()

public class Client(string username, string password, int? timeout) 
{
    _timeout = timeout ?? 60;
}

I dislike this solution, because the default value is no longer exposed in the constructor's signature (which acts as excellent/free documentation).

3) Handle null values in Client() with a default value

public class Client(string username, string password, int? timeout = 60) 
{
    _timeout = timeout ?? 60;
}

I dislike this solution because 1) it's not immediately obvious how null will be handled (requires more documentation), and 2) the default value is duplicated (it would stink if someone modified one but forgot to modify the other).

4) Use null operator and usedefaultparam keyword in Main

static void Main(string[] args)
{
    Client client = new Client(Username, Password, Timeout ?? usedefaultparam);
    // ...
}

I like this solution because it's easy to read and grows nicely if I add more optional parameters.

I dislike it because the usedefaultparam keyword doesn't seem to exists.

Thus my question:

Does something like option 4 exist? If not, is there a nicer, fifth pattern I am not thinking of?

Aucun commentaire:

Enregistrer un commentaire