C# - 何时调用 base.On Something?

2023-12-19

我在用着Windows.Forms并且必须继承一些控件来提供自定义行为。这种继承显然会导致方法重写。

所以,这是问题- 在这种情况下调用的顺序base.OnSomething(...)真的可以影响程序的可见行为吗?

protected override OnRetrieveVirtualItem(RetrieveVirtualItemEventArgs e)
{
    // base.OnRetrieveVirtualItem(e); - Could this potentially break something?

    // Perform your custom method.
    // ...

    base.OnRetrieveVirtualItem(e); // Is this always "correct"?
}

据我所知,在重写与绘制相关的方法时,这个顺序可能很重要(OnDrawItem, ...),但我猜有还有其他一些朝自己腿开枪的方法吗因为Windows.Forms执行大量非托管代码调用,可能会产生副作用。

那么,什么时候它可能重要呢​​?选择正确的调用位置的经验法则是什么?base这些情况下的方法?


您只需要致电base.SomeVirtualMethod当该 API 的文档指定您应该这样做时。否则,它应该被暗示为可选的。要求您调用基本方法但没有明确声明的 API 设计得很糟糕。

需要基调用的原因是糟糕的设计,因为您永远无法期望覆盖您的方法的人会做什么,并且您无法确定他们会调用基方法来执行任何必需或关键代码。

简而言之,请参阅文档,否则通常没有必要。 .NET Framework 是根据此类准则设计的,因此大多数虚拟方法不需要调用基类。那些做的事情都有记录。

感谢 roken,他指出了调用基本虚方法的一个非常重要的原因,就是在使用事件时。但是,我的反驳观点(情况并非总是如此)仍然适用,特别是如果您使用不遵循 .NET 习惯用法和模式的第三方库或类,则没有任何确定性。以这个例子为例。

namespace ConsoleApplication12
{
    using System;
    using System.Diagnostics;

    class Foo
    {
        public Foo() {
        }

        public event EventHandler Load;

        protected virtual void OnLoad() {
            EventHandler handler = Load;

            if (handler != null) {
                handler(this, new EventArgs());
            }

            Debug.WriteLine("Invoked Foo.OnLoad");
        }

        public void Run() {
            OnLoad();
        }
    }

    class DerivedFoo : Foo
    {
        protected override void OnLoad() {
            base.OnLoad();
            Debug.WriteLine("Invoked DerivedFoo.OnLoad");
        }
    }

    class Program
    {
        static void Main(string[] args) {
            DerivedFoo dFoo = new DerivedFoo();

            dFoo.Load += (sender, e) => {
                Debug.WriteLine("Invoked dFoo.Load subscription");    
            };

            dFoo.Run();
        }
    }
}

如果运行此示例,您将获得三个调用Foo.OnLoad, DerivedFoo.OnLoad,以及事件订阅dFoo.Load。如果您注释掉对base.OnLoad in DerivedFoo,您现在只会获得一次调用DerivedFoo.OnLoad,并且基地和订户没有接到电话。

这一点仍然很重要,那就是取决于文档。仍然不确定基本虚拟方法实现是否调用其订阅者。所以这一点应该很清楚。幸运的是,由于框架设计者的帮助,.NET 框架与 .NET 事件模型非常一致,但我仍然无法强调要始终阅读 API 文档。

当您根本不处理事件而是处理抽象基类之类的事情时,它会发挥很大的作用。如何知道是否调用抽象类的基事件?抽象类是否提供默认实现,或者是否期望您提供它?

文档是定义虚拟会员合同的最有力、最清晰的方式。这就是 .NET 框架设计团队通常为交付的抽象类提供至少一个具体实现的原因之一。

我认为 Krzysztof Cwalina 在框架设计指南中说得最好。

我遇到的一个常见问题是虚拟成员的文档是否应该说明重写必须调用基本实现。答案是重写应该保留基类的约定。他们可以通过调用基本实现或其他方式来完成此操作。很少有成员可以声称保留其合同(在覆盖中)的唯一方法是调用它。在很多情况下,调用基础可能是保留合同的最简单方法(文档应该指出这一点),但这很少是绝对必需的。

我完全同意。如果您覆盖基本实现并决定不调用它,您应该提供相同的功能。

我希望这能澄清我在评论中遇到的一些困惑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# - 何时调用 base.On Something? 的相关文章

随机推荐

  • 即使 INSERT IGNORE 忽略插入也会锁定表吗?

    在 MySQL 中 如果我有一个 INSERT IGNORE 命令 由于唯一性约束 该命令最终不会插入到表中 它是否询问并等待写锁 或者MySQL是否识别IGNORE关键字 并在写锁之前使用读锁 并且只有当它确实需要写时才请求写锁 这取决于
  • 在jquery中将文本框设置为只读并将背景颜色设置为灰色

    再会 我想在我的中创建一个文本框jsp成为readonly其背景颜色为灰色disable在 Jquery 中 以下是我的代码 if a billAccountNumber attr readonly true 我不喜欢使用attr disa
  • 服务在 SQL Server 配置管理器中不可见

    我已经安装了 SQL Server 2008 Management Studio Express 32 位 我已成功安装它 但当我尝试连接 SQL Server 时出现错误 然后我想从 SQL Server 配置管理器打开服务 但我看不到任
  • 将函数传递给子例程时,虚拟过程“f”中的接口不匹配

    我正在尝试编写一个具有两个参数的子例程 用于最小化 数组x任意长度 一个函数f接受该长度的数组并返回一个标量 示例模块 module foo contains subroutine solve x f real dimension inte
  • 如何通过 iPhone 上的网页检查应用程序是否已安装

    我想创建一个网页 一个将 iPhone 重定向到应用商店 https en wikipedia org wiki App Store 28iOS 29如果 iPhone 没有安装该应用程序 但如果 iPhone 安装了该应用程序 我希望它打
  • 在面板内的控件顶部绘图 (C# WinForms)

    我知道这个问题已经被问过多次 但到目前为止我还没有找到一个好的解决方案 我有一个带有其他控件的面板 我想在它上面以及面板中所有控件的顶部画一条线 我遇到了 3 种解决方案 它们都没有按照我想要的方式工作 获取桌面 DC 并在屏幕上绘制 如果
  • chm hhk 中的关键字标签

    我目前正在检查 CHM 的二进制索引构建 但我注意到示例项目中的一些 hhk 例如生成的 Sphinx 有一个 关键字 标签 该标签似乎没有记录在chmspec http www nongnu org chmspec latest Site
  • 有没有办法通过反射获取类型的别名?

    我正在编写一个简单的代码生成应用程序来从 DB2 数据库模式构建 POCO 我知道这并不重要 但我更喜欢使用类型别名而不是实际的系统类型名称 如果可用 即 int 而不是 Int32 有没有一种方法可以使用反射来获取类型的别名而不是实际类型
  • 在 VS 中以编程方式打开解决方案时,如何才能将文件添加到最近项目的 MRU 列表中?

    当使用以下方式在加载项 扩展 在我的例子中为 VS2012 中以编程方式打开解决方案时解决方案 打开 http msdn microsoft com en us library vstudio envdte solution open as
  • 如何在 Python 中进行相对导入?

    想象一下这个目录结构 app init py sub1 init py mod1 py sub2 init py mod2 py 我正在编码mod1 我需要从中导入一些东西mod2 我该怎么做呢 I tried from sub2 impo
  • TFS 迭代积压仅显示用户故事而不是任务

    在使用敏捷流程模板的 TFS 2015 中 board对于 故事 待办事项列表仅显示故事 当前迭代的面板显示故事下的所有任务 这对于大多数团队来说都是有意义的 我们正在将我们的工作分解成比平常更小的故事 因此避免任务崩溃 https www
  • python 尝试一下 except

    我的问题很简单 我有一个try except代码 在尝试中 我进行了一些http请求尝试 在例外中 我有几种方法来处理我遇到的异常 现在我想在我的代码中添加一个时间参数 这意味着尝试只会持续 n 秒 否则用 except 捕获它 用自由语言
  • 如何在.NET 6库中引用ASP.NET Core 6类型?

    我正在为我的组织开发内部图书馆 我需要引用通常 属于 网络应用程序的某些类型 例如 提供一些扩展 WebApplicationOptions HttpContext 如果我使用
  • Python 偏导数简单

    我对用 Python 计算偏导数感兴趣 我见过计算单变量函数导数的函数 但没有见过其他函数 找到具有以下功能的东西就太好了 f x y z 4xy xsin z x 3 z 8y part deriv function f variable
  • Mercurial如何检索执行hg推送的真实用户

    在服务器站点上 hg tip显示执行 hg Push commit 的用户 数据取自 hgrc 的 user 部分 我可以把我喜欢的任何东西放在那里 但如何在服务器上了解真正这样做的人hg push 你需要维护一个pushlog手动跟踪这一
  • 在 Javascript 中将图像转换为二进制数据或字符串

    我正在使用 Chrome Extension 上的 XMLHttp Request 将图像文件上传到 TWITPIC 我需要将图像作为有效负载发送 有没有办法做到这一点 我找到了这个链接在javascript中将图像转换为二进制数据 htt
  • Python 3 中真正的私有变量

    所以我知道如何在 python 中使变量 私有 如下所示 class Foo def init self self private bar 这 有效 但无效 如下所示 foo Foo private in vars foo False Fo
  • 在模块 guava-20.0.jar (com.google.guava:guava:20.0) 中发现重复的类 com.google.common.util.concurrent.ListenableFuture

    当我使用implementation com google firebase firebase inappmessaging display 17 2 0 in my app build gradle 我收到此错误 Duplicate cl
  • jQuery - 用 DIV 跟随光标

    如何使用 jQuery 使 DIV 跟随光标 您不能使用 a 跟随光标DIV 但你可以画一个DIV当移动光标时 document on mousemove function e your div id css left e pageX to
  • C# - 何时调用 base.On Something?

    我在用着Windows Forms并且必须继承一些控件来提供自定义行为 这种继承显然会导致方法重写 所以 这是问题 在这种情况下调用的顺序base OnSomething 真的可以影响程序的可见行为吗 protected override