是否将.NET中的访问修饰符从私有更改为公共更改?

时间:2017-08-30 07:59:23

标签: c# .net

让我们考虑理论上的例子

  • ApplicationA
  • SharedLibrary - > ClassA
  • Plugin

如果您更改了ClassA中的SharedLibrary,请更新ApplicationA以使用新的SharedLibrary,但不要更新Plugin。你还能加载Plugin(通过Assembly.CreateInstance还是MEF)?

.NET正在从private - >更改访问修饰符public一个重大改变?

这篇文章似乎暗示即使添加一些东西也会是一个突破性的变化,但是会谈论重载等,而不是修饰符。 https://docs.spring.io/spring/docs/4.3.10.RELEASE/spring-framework-reference/htmlsingle/#cache-annotations-cacheable-condition

编辑ShareLibrary中使用了Plugin类。因此要问的原因。

此致

2 个答案:

答案 0 :(得分:4)

是的,制作private成员public可能会破坏构建。

考虑这个课程:

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);
}

这段代码:

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

这将编译好,并将打印3

现在,如果您公开Method()的私有重载,则上面的代码将不再编译。您将收到以下编译错误:

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

但是,关于您对该插件的问题 - 您没有指定它是否使用SharedLibrary。如果没有,则更改SharedLibrary无法破坏插件。

如果确实如此,那么你可能会得到一个讨厌的运行时错误,具体取决于它如何使用它 - 但实际上并不能保证这种情况发生。

以下是使用插件的示例,如果您将方法公开,则会在运行时中断。

首先,我们有一个包含以下类的共享类库:

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);
}

其次,我们有一个插件类,使用反射来使用该库,如下所示:

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;
    }
}

现在假设我们有一个使用共享类的应用程序,并且还在其输出文件夹中包含插件程序集DLL的副本:

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);
}

这样就可以了。

现在假设你将private int Method(int x = 0)公开并重新编译共享类库和使用它的应用程序,但不要重新编译插件 - 即你继续使用旧的插件DLL。

现在,如果您运行该程序,您将获得Ambiguous match found例外。

这是一个通过公开一个甚至没有被该插件使用的方法来破坏未更改的插件的示例。

答案 1 :(得分:2)

从您关联的网站: 一些公共表面区域突破的变化是显而易见的:将公共方法变为私有方法

是的,这是一个重大变化,但如果你不在插件中使用这个类和方法,它就不会破坏你的程序。 您可以将架构更改为依赖于接口而不是插件中的实现。