Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重写未标记为虚拟的接口方法_C#_Overriding_Virtual - Fatal编程技术网

C# 重写未标记为虚拟的接口方法

C# 重写未标记为虚拟的接口方法,c#,overriding,virtual,C#,Overriding,Virtual,我正在写一个log4net appender。他们有一个AppenderSkeleton类,该类实现了IAppender: public abstract class AppenderSkeleton : IBulkAppender, IAppender, IOptionHandler AppenderSkeleton类的工作方式是实现IAppender的DoAppend()方法,并为您做大量工作,比如调用过滤器链,然后调用一个名为Append()的抽象方法。虽然这是合理的,但我希望

我正在写一个log4net appender。他们有一个AppenderSkeleton类,该类实现了IAppender:

public abstract class AppenderSkeleton : IBulkAppender, 
    IAppender, IOptionHandler
AppenderSkeleton类的工作方式是实现IAppender的DoAppend()方法,并为您做大量工作,比如调用过滤器链,然后调用一个名为Append()的抽象方法。虽然这是合理的,但我希望在过滤器运行之前执行一些代码。我可以自己实现IAppender接口,但一开始我想我应该在派生类中重写DoAppend(),完成我的工作,然后调用base.DoAppend()。在这一点上,我注意到AppenderSkleton没有将DoAppend()标记为virtual,因为我得到一个编译器错误,表明我无法重写该方法,因为它没有标记为virtual

然后,我让我的类从IAppender派生,并显式实现了IAppender.DoAppend()方法。我很惊讶代码编译时没有出现问题。下面是我的DoAppend()方法:

我还没有试过运行它,但想知道是否有人现在可能会问运行时将如何处理这个实现

谢谢,
尼克

如果有人没有将他的方法标记为虚拟,那么就没有办法覆盖它。唯一的选择是实现自己的
IAppender

另外,请注意,您不重写接口方法,而是实现它们

但是,您甚至不需要重写此方法。
根据文档,
DoAppend

在将实际日志委派给特定于子类的Append方法之前,执行阈值检查并调用过滤器

您不需要重写
DoAppend
方法,因为它描述了通用算法。
有点像

您需要重写抽象的
Append
方法:

protected override void Append(LogginEvent loggingEvent)
{
    // Your actions here
}

@Rob的答案是正确的——调用哪个方法(基方法或派生方法)取决于您如何调用它。这将使它变得相当脆弱

我建议使用组合而不是继承。不要让你的类从AppenderSkleton继承,让它包含AppenderSkleton的实例,并在你选择的地方使用它的方法


如果声明一个私有变量来实现类也实现的接口之一,VisualStudio甚至有一个快速的“通过私有变量实现接口”选项。它快速为您的类生成代理模式,调用私有成员上的相应方法。

您的类不是从
IAppender
派生的,它实现了
IAppender
。它直接派生自
对象
,而对象没有方法
DoAppend
,因此
base.DoAppend
是一个错误。只有将方法转换为
iaappender
时,才会调用该方法。如果它被强制转换为
AppenderSkeleton
,您的代码将不会运行。我真的只是想回答运行它。“我还没有尝试运行它”——为什么不呢?你不觉得这是得到答案的最好方法吗?堆栈溢出不是用来做你自己可以轻松完成的事情的。如果您想知道代码的作用,请编译并运行它。如果你想帮助你理解某件事,或者不能让某件事起作用,就发一个好的、具体的问题。另请参见。只是还没来得及运行它。然而,无论运行它的结果如何,我仍然会有一个问题:为什么这样做能够消除编译器错误。谢谢。但我要么需要重写DoAppend(),要么自己实现IAppender,因为我想在运行过滤器之前运行代码。我不想重新实现DoAppend()所做的所有代码,因此我试图找到一种方法,让我实现DoAppend(),完成我需要做的工作,然后调用基类的DoAppend()。是的,我正在考虑使用包含(合成),这可能就是我的方法。我不想依赖于通过使用reflector并从那里复制逻辑来实现我自己的DoAppend()。这就是为什么我最初试图找到一种方法来覆盖AppenderSkeleton DoAppend(),令人惊讶的是,我没有错误地编译了它,所以对此有些惊讶。我想如果我知道所有使用该实例的代码都会将其视为IAppender的实例,而不是AppenderSkeleton的实例,那么它应该与我已经完成的工作一起工作。
protected override void Append(LogginEvent loggingEvent)
{
    // Your actions here
}