2

Lets consider a theoretical example

  • ApplicationA
  • SharedLibrary -> ClassA
  • Plugin

If you change a ClassA in SharedLibrary, update ApplicationA to use the new SharedLibrary but do NOT update the Plugin. Would you still be able to load the Plugin (via a Assembly.CreateInstance or MEF)?

In .NET is changing an access modifier from private -> public a breaking change?

This article seems to imply even adding something would be a breaking change, however talks about overloads, etc, not modifiers. https://blogs.msdn.microsoft.com/ericlippert/2012/01/09/every-public-change-is-a-breaking-change/

EDIT: The ShareLibrary class is used in the Plugin. Hence the reason for asking.

Regards

Oliver
  • 35,233
  • 12
  • 66
  • 78
  • What happens when you try it? – tymtam Aug 30 '17 at 08:08
  • 1
    Title and body disagree. Which direction are you making the change? I'd assume the one in the title since it's the more likely to be questionable. – Damien_The_Unbeliever Aug 30 '17 at 08:23
  • "Breaking change" has no hard definition. For any change you can make to a public interface, maybe so simple as adding something, someone can come up with an example that will break after that change. The question is if that example is to obscure **for you** to qualify as breaking change or not. Other may have their personal diverging opinion. – Ralf Aug 30 '17 at 09:17
  • @Damien_The_Unbeliever thanks man, sorry mistake was in the body :) – Oliver Aug 30 '17 at 11:38

2 Answers2

4

Yes, making a private member public can break the build.

Consider this class:

public class Test
{
    private int Method(int x = 0) => x;
    public int Method(int x = 1, int y = 2) => x + y;

    public int Foo => Method(0);
}

And this code:

class Program
{
    static void Main()
    {
        Console.WriteLine(new Test().Method());
    }
}

This will compile OK, and will print 3.

Now if you make public the private overload of Method() the code above will no longer compile. You will get the following compile error:

Error   CS0121  The call is ambiguous between the following methods or properties: 
'Test.Method(int)' and 'Test.Method(int, int)'  

However, with regard to your question about the plugin - you did not specify whether it uses SharedLibrary. If it doesn't, then changing SharedLibrary cannot break the plugin.

If it does, then you could get a nasty runtime error, depending on how it uses it - but that's actually not guaranteed to happen.


Here's an example of using a plugin which WILL break at runtime if you make a method public.

Firstly, we have a shared class library containing the following class:

public class Test
{
    private int Method(int x = 0) => x;
    public int Method(int x = 1, int y = 2) => x + y;

    public int Foo => Method(0);
}

Secondly, we have a plugin class that uses that library using reflection like so:

public class Plugin
{
    public int Test()
    {
        var testClass = typeof(Test);
        var testInstance = Activator.CreateInstance(testClass);
        var method = testClass.GetMethod("Method");
        int result = (int)method.Invoke(testInstance, new object[]{1, 2});
        return result;
    }
}

Now suppose we have an application that uses the shared class, and also contains a copy of the plugin assembly DLL in its output folder:

static void Main()
{
    Console.WriteLine(new Test().Method(1, 2));

    var plugin       = Assembly.LoadFile(Path.GetFullPath("PluginLibrary.dll"));
    var testClass    = plugin.GetType("PluginLibrary.Plugin");
    var testInstance = Activator.CreateInstance(testClass);
    var method       = testClass.GetMethod("Test");
    int result       = (int) method.Invoke(testInstance, null);

    Console.WriteLine(result);
}

This will run ok.

Now suppose you make the private int Method(int x = 0) public and recompile the shared class library and the application that uses it, but DO NOT recompile the plugin - i.e. you continue using the old plugin DLL.

Now if you run the program you'll get an Ambiguous match found exception.

This is an example where you have broken an unchanged plugin by making public a method that wasn't even being used by that plugin.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
2

From the website you linked : Some public surface area breaking changes are obvious: making a public method into a private method

Yes it is a breaking change but if you don't use this class and method in the plugin, it won't break your program. You may change your architecture to rely on interfaces instead of implementations in your plugins.

Guillaume
  • 12,824
  • 3
  • 40
  • 48
  • Thanks for pointing out my mistake. I've deleted the answer for it was wrong. :) – Kostya Aug 30 '17 at 10:53
  • Changing the architecture would not be possible. The whole idea is to minimize the extent of the changes, to the point where I don't even want to recompile the plugins. – Oliver Aug 30 '17 at 11:36
  • It might be interesting for a next version of you want to build something more reliable / future proof or for your next project with plugins ;) – Guillaume Aug 31 '17 at 06:49