Alain Alain - 3 months ago 9
C# Question

Ambiguous method definitions, but want to maintain backwards compatibility

I have this old method signature that I want to deprecate:

[Obsolete("This method has been replaced with one that uses an arguments object")]
public static T PollUntilReady<T>(
Func<T> functionThatMight503,
double minPollInterval = 0d,
double maxPollInterval = double.MaxValue,
double maxPollTotalTime = double.MaxValue);


I want to replace this with a more forward-looking variation that uses a parameters argument for the various options that may be added in the future:

public static T PollUntilReady<T>(
Func<T> functionThatMight503,
PollingOptions pollingOptions = null);


The problem is if no options are specified, the compiler complains that the method call is ambiguous. ("The call is ambiguous between the following methods...")

Is there any way I can resolve this without breaking backwards compatibility, renaming the new function, or compromising the new method's flexibility (optional options object)?

Answer

You can implement it as two functions instead:

public static T PollUntilReady<T>(Func<T> functionThatMight503)
{
    return PollUntilReady(functionThatMight503, null);
}

public static T PollUntilReady<T>(
    Func<T> functionThatMight503,
    PollingOptions pollingOptions)
{
    throw new NotSupportedException(); //Whatever
}

When called with only a single argument, the compiler can now resolve the ambiguity since it has a function to choose from that doesn't require any defaults.

This does mean that the default value for pollingOptions is now baked into your code rather than the calling code, which means that if you choose to change the default value later, older code will receive the new default even without recompilation.


This avoids ambiguity thanks to the overload resolution rule:

Otherwise if all parameters of MP have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in MQ then MP is better than MQ

from section 7.5.3.2 of the C# language spec.