Projects reference and Methods signature issue

47 views Asked by At

I got a strange issue after i altered a method signature on a referenced project.

Let me explain what happened: I got 50 projects P1,P2,..,P50 that depends on a common project C0 that contains common functionality. P1 to P50 are distributed among customers and i dont want to rebuild and redistribute them unless it is necessary.

P1 to P50 Projects contains this class

public partial class LogView: UserControl {
    private void buttonReadUnit_Click(object sender, EventArgs e) {
        readUnit();
...

public partial class LogView : IView {
    public void readUnit() {    
        UnitBusyMode.Begin(Application.OpenForms[0],true);
...

C0 contains

public partial class UnitBusyMode : Form{
   public static Thread Begin(Form owner, bool cancellable = false){
...

Yesterday I changed the method Begin into this

public static Thread Begin(Form owner, bool cancellable = false, int setTemplate= TEMPLATE_NORMAL){

Then i rebuild the project C0 and distributed it to customers. But at this point I realized that many P projects rise an error on the readUnit(); invocation line. The error was something like: readUnit() Cant find a method with the signature Begin(Form owner, bool cancellable = false).

That's very strange because the new signature is compatible with the old UnitBusyMode.Begin(Application.OpenForms[0],true) call.

Recompiling C0 project didn't help. The only way to fix this issue was to recompile all the P1 to P50 projects.

It's strange because the error did not rise on the Begin method invocation line: UnitBusyMode.Begin(Application.OpenForms[0],true);

but on the call to the method readUnit();

Do you know what could cause this issue and how to prevent it?

thank you

1

There are 1 answers

0
Peter B On BEST ANSWER

Optional parameters in C# are syntactic sugar that are implemented by stuffing the default value as an actual parameter into all method calls that don't specify a parameter value of their own.

This normally goes unnoticed, until you separate a method and its caller(s) into separate DLLs, and decide to add an optional parameter to the method. All projects that call it must then be recompiled, because if you don't they will keep looking for a method with the original signature, but that method no longer exists - there is now only a method with one additional (required...!) parameter, and the default value only gets added to the call site if you recompile it.

For cases where you are going from 0 optional parameters to 1, you can work around this this by adding a new overload that adds the new parameter. But that becomes quite hard (if not impossible) if the method in question already has an optional parameter and you want to add another. The only solution may then be to recompile all client programs.


PS This issue and the fixes/workarounds have been known since optional parameters were introduced around 2010 with C# 4, see e.g. https://haacked.com/archive/2010/08/10/versioning-issues-with-optional-arguments.aspx/