修改公共财产的访问修饰符是一个突破性的变化吗?

mku*_*kus 21 c#

如果我将公共属性的setter的访问修饰符从private更改为public,是否会导致引用它的其他程序集中的任何重大更改?

Eri*_*ert 34

更新:这个问题是我2012年1月的博客主题.谢谢你这个好问题!


我假设通过"破坏变化"你的意思是"当我重新编译依赖于这个程序集的代码时,用于编译的代码是否仍然编译?"

根据这个定义,严格地说,是的,将过去属于私有的属性设置者公开是一个突破性的变化.假设你有这个代码:

// Assembly Alpha
public class Charlie
{
    public int P { get; private set; }
}
public class Delta
{
    public int P { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后在另一个引用Alpha的程序集中:

// Assembly Echo
class Foxtrot
{
    static void M(Action<Charlie> f) {}
    static void M(Action<Delta> f) {}
    static void Golf()
    {
        M(y=>{y.P = 123;});
    }
}
Run Code Online (Sandbox Code Playgroud)

你编译程序集Echo.Foxtrot类有一个方法Golf,它可以对M进行超载分辨.M有两个重载; 一个对查理采取行动的人和一个对三角洲采取行动的人.如果lambda参数y的类型为Charlie,那么lambda主体会产生可访问性错误,因此M的重载不是适用的候选者.重载决策选择第二个重载并编译成功.

现在你更改程序集Alpha,以便Charlie.P的setter是公共的.你重新编译Echo.现在你得到一个重载分辨率错误,因为M的两个重载同样有效,并且两者都不比另一个好.由于Alpha的变化,Echo的编译失败.你对Alpha的改变是一个突破性的变化.

问题不在于"这是一个突破性的变化吗?" 显然是; 几乎所有的变化都是某种突破性变化.问题应该是突破性变化是否真的会在实践中打破任何人,如果是这样,与新功能的好处相比,修复中断的成本是多少?

  • @kvb:我曾经打电话给航空公司更改预订,电话上乐于助人的女士说"如果出现问题,这是您的确认号码:153ADN6,那是1-5-3-Alpha-Dog-November-6 ",我说"谢谢,但不是Delta国际无线电代码字D?" 她说:"我们在这家航空公司没有这么说!*"我告诉你,在航空公司打电话给*人*是很难的; 得到一个聪明而有趣的人,谁知道国际电台字母表启动是一个罕见的确实. (22认同)
  • 布拉沃怎么了? (2认同)
  • 如果它实际上是你正在调用的Delta,那将会更有趣. (2认同)

Jef*_*Sax 18

这是一个重大变化,因为它可能导致现有代码不再编译.

某些语言不允许您覆盖属性而不覆盖所有可见访问器.VB就是这样一种语言.

假设您有以下C#类:

namespace TestLibrary
    public class A {
        public virtual int X { 
            get { return 0; } 
            private set { Console.WriteLine("A.set_X called."); } 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在引用您的库的VB项目中,您有一个类定义:

Class B : Inherits TestLibrary.A
    Public Overrides ReadOnly Property X As Integer
        Get
            Return MyBase.X
        End Get
    End Property
End Class
Run Code Online (Sandbox Code Playgroud)

注意ReadOnly属性上的修饰符.这在VB中是必需的,因为您只定义了getter.如果将其遗漏,则会出现编译时错误:

没有'ReadOnly'或'WriteOnly'说明符的属性必须同时提供'Get'和'Set'.

现在,private从C#类的setter中删除修饰符:

namespace TestLibrary
    public class A {
        public virtual int X { 
            get { return 0; } 
            set { Console.WriteLine("A.set_X called."); } 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您现在将在VB代码中遇到编译时错误:

'Public Overrides ReadOnly Property X As Integer'不能覆盖'Public Overridable Property X As Integer',因为它们的区别在于'ReadOnly'或'WriteOnly'.

在进行更改后,引用库的相同代码无法编译,因此这是一个重大更改.

  • 好的!语言间休息是最棘手的. (5认同)

Joh*_*ers 5

这取决于你想要"破坏变化"的严格程度.

一个定义是:它是否会破坏引用代码的构建或执行.

另一个是,其他代码可以确定您进行了更改.

根据第一个定义,这不是一个突破性的变化.根据第二个定义,这是一个突破性的变化.