Search code examples
c#c#-4.0named-parameters

Pass Named Parameter Conditionally


I have a struct which takes 3 named parameters in to the constructor...

public struct MyData
{
    private readonly double _value1;
    private readonly double _value2;
    private readonly double _value3;

    public MyData(
        double value1 = 1.0,
        double value2 = 2.0,
        double value3 = 3.0)
    {
        _value1 = value1;
        _value2 = value2;
        _value3 = value3;
    }
}

The method call that creates the class receives in three nullable doubles which I want to use to create the MyData class only if the nullable doubles are not null...

public MyData CreateMyData(double? value1, double? value2, double? value3)
{
    MyData myData;
    if (value1.HasValue)
    {
        if (value2.HasValue)
        {
            if (value3.HasValue)
            {
                myData = new MyData(value1, value2, value3); 
            }
            else
            {
                myData = new MyData(value1, value2); 
            }
        }
        else
        {
            if (value3.HasValue)
            {
                myData = new MyData(value1, value3: value3); 
            }
            else
            {
                myData = new MyData(value1); 
            }
        }
    }
    else
    {
        if (value2.HasValue)
        {
            if (value3.HasValue)
            {
                myData = new MyData(value2: value2, value3: value3); 
            }
            else
            {
                myData = new MyData(value2: value2); 
            }
        }
        else
        {
            if (value3.HasValue)
            {
                myData = new MyData(value3: value3); 
            }
            else
            {
                myData = new MyData(); 
            }
        }
    }
    return myData;
}

Is there a nicer way to write this method without modifying the MyData class? I.e. Can I conditionally pass named parameters or can I pass an indicator to represent the default named parameter value?


Solution

  • public MyData(
        double? value1 = null,
        double? value2 = null,
        double? value3 = null)
    {
        _value1 = value1 ?? 1.0;
        _value2 = value2 ?? 2.0;
        _value3 = value3 ?? 3.0;
    }
    

    This way, you can pass the nulls directly and won't suffer from the combinatorial explosion.

    Also, if you ever decide to change the defaults, it would work even without recompiling all users of this code.