【问题标题】:Make a c# function non-private, mark it as final, or seal its declaring type将 c# 函数设为非私有,将其标记为 final,或密封其声明类型
【发布时间】:2017-02-27 02:51:57
【问题描述】:

我正在维护一些旧的 C# 代码,不能过多地更改其结构。我试图以安全的方式减少一些现有的编译器警告。某些功能给了我以下警告:

警告 CS0108 'Function(string, string)' 隐藏了继承的成员 'xyz.Function(string, string)'。如果要隐藏,请使用 new 关键字。

我认为隐藏该继承功能是故意的,因为该软件已经成功使用多年。我认为添加“new”关键字以将此函数声明为

private new void Function(string parm1, string parm2)

警告按预期消失了,但出现了这个警告:

警告 CA2222 将 'Function(string, string)' 设为非私有,将其标记为 final,或密封其声明类型。该方法最初是在基类“BaseClassName”中定义的。

除了禁止显示此警告之外,我不确定我可以使用的最安全(即不改变行为)选项是什么?我不认为我应该使这种方法成为非私有的(我认为这意味着“公共”)。我不确定如何使它最终或密封,以及这样做是否是正确的解决方案。

【问题讨论】:

  • 您能否提供更多有关带有原始警告(使用新关键字...)的类及其扩展的类的详细信息?听起来最初的意图最有可能将原始功能标记为虚拟功能并将扩展功能标记为覆盖。不过,我需要更多细节才能确定。
  • 可能是基类中的“受保护”函数?
  • 这是上面代码隐藏的基类中的方法定义: public abstract class BaseCodeListPage : BasePage ... protected void AddOnClientClick(string parm1, string parm2) { ... }
  • ...包含这个有问题的函数的类定义如下: public partial class myListPage : BaseCodeListPage
  • 所以,是的,正如 Yuri 所怀疑的那样,该函数在基类中受到保护。我不确定触摸它是否安全。

标签: c# compiler-warnings


【解决方案1】:

除非可以通过反射访问此方法,否则请删除“new”关键字,然后重命名(也更改任何调用站点)。无论如何,该方法是私有的,因此它只能在同一个类中使用,除非它是由委托传递的(然后名称无关紧要)或者如果使用反射来访问它。

在假设代码正确的情况下,任何对该方法的调用都是故意的。虽然我会检查它们并检查调用站点是否调用了错误的方法。


对方法的可见性进行任何更改都是有问题的,因此请避免这样做※。关于创建类sealed,这也是一个重大更改,因为可能存在继承自该类的第三方代码,因此也要避免这种情况。

※:由于可能存在使用该成员的第三方代码,因此可见性降低最严重,因此这是一项重大更改。增加可见性(例如使私有方法受保护或公开)可能会破坏类型的封装,暴露成员可能会允许第三方代码混淆该类型对象的状态,所以要小心。

【讨论】:

  • 谢谢,很高兴知道这一点,但是开始重命名方法或其他任何事情可能超出了我现在可以做的范围。幸运的是,没有任何第三方应用程序使用此代码。
  • @JouniJuntunen 在这种情况下,您现在可以留下警告,这将提醒您或其他人对其进行调查。另一件事,研究版本控制(以便您可以分支并尝试不同的解决方案)、自动化测试(以便您可以快速进行回归测试),这些应该可以减轻您或您的同事在修改代码时可能产生的任何担忧。
  • 是的,我想我现在先离开它。与其说是害怕破坏东西,不如说是首先接触代码的成本。我们刚刚恢复了这个旧代码并进行了一些增强,这些增强不是非常具有侵入性和复杂性。虽然我正在熟悉现有代码,但我认为通过删除至少现有的一些警告,我可能会使其更清洁和更容易使用。
【解决方案2】:

您可以忽略警告 - 它被错误地触发了。也就是说,private new 有点代码味道,可能表明存在更深层次的问题。

请参阅here 了解它发生的原因。担心有人会出现并覆盖您的new 方法。

如果您必须更改访问修饰符,则方法应标记为 final 或其类型应密封以防止方法被覆盖。

但是,默认情况下,C# 中的方法是最终的。将方法标记为密封的(在其他语言中也称为 final)C# 仅防止 进一步 覆盖。

该警告仅适用于您的新方法是:

public/protected/internal virtual new void Function(string parm1, string parm2)

在这种情况下,解决方案是删除 virtual 关键字

【讨论】:

  • 谢谢,对于像我这样的 c# 新手来说,这是非常有价值的信息。
猜你喜欢
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 2016-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
相关资源
最近更新 更多