当重写一个抽象方法并尝试调用我目前正在覆盖的基类方法时,我发现了一个非常奇怪的问题.
//In Dll "A" namespace Rhino.Etl.Core.Operations { using System; using System.Collections; using System.Collections.Generic; public class Row {} public interface IOperation { IEnumerable<Row> Execute(IEnumerable<Row> rows); } public abstract class AbstractOperation : IOperation { public abstract IEnumerable<Row> Execute(IEnumerable<Row> rows); } public abstract class AbstractDatabaSEOperation : AbstractOperation { } public abstract class sqlBulkInsertOperation : AbstractDatabaSEOperation { public override IEnumerable<Row> Execute(IEnumerable<Row> rows) { Console.WriteLine("sqlBulkInsertOperation"); return rows; } } } //In console app "B" namespace MyStuff { using System; using System.Collections; using System.Collections.Generic; class Program { static void Main(string[] args) { ActualEtlOperation e = new ActualEtlOperation(); e.Execute(new Row[0]); Console.ReadLine(); } } public abstract class sqlBulkInsertWithTruncateOperation : sqlBulkInsertOperation { public override IEnumerable<Row> Execute(IEnumerable<Row> rows) { Console.WriteLine("Truncate"); base.Execute(rows); return rows; } } public class ActualEtlOperation : sqlBulkInsertWithTruncateOperation { } }
基本上,sqlBulkInsertOperation没有做我需要它做的事情,所以我需要在我通过覆盖它来调用Execute(rows)之前和之后做一些工作.但是不执行sqlBulkInsertOperation.Execute(Rows)中的代码.
在Visual Studio中的调试器中运行此代码时,调试器的代码未执行.当我将鼠标悬停在Visual Studio编辑器中的“base”上时,它知道基类的类型为sqlBulkInsertOperation.
我错过了什么?
解决方法
编辑:我发现了这个问题……具有讽刺意味的是,我对Eric的“心灵调试”评论并没有那么遥远,给出了
this blog post.这是一个简短但完整的程序,它将展示正在发生的事情……
using System; using System.Collections.Generic; public class Row {} public abstract class BaseDatabaSEOperation { public abstract IEnumerable<Row> Execute(IEnumerable<Row> rows); } public abstract class sqlBulkInsertOperation : BaseDatabaSEOperation { public override IEnumerable<Row> Execute(IEnumerable<Row> rows) { Console.WriteLine("In sqlBulkInsertOperation.Execute"); foreach (var row in rows) { yield return row; } } } public class MyOverride : sqlBulkInsertOperation { public override IEnumerable<Row> Execute(IEnumerable<Row> rows) { Console.WriteLine("In MyOverride.Execute"); return base.Execute(rows); } } class Test { static void Main() { BaseDatabaSEOperation x = new MyOverride(); x.Execute(new Row[0]); } }
这将打印“在MyOverride.Execute”,但它*不会“打印”在sqlBulkInsertOperation.Execute“…因为该方法是使用迭代器块实现的.
当然,您可以更简单地演示这一点:
using System; using System.Collections.Generic; class Test { static IEnumerable<string> Foo() { Console.WriteLine("I won't get printed"); yield break; } static void Main() { Foo(); } }
什么都没有使用方法的返回值 – 它被传递回Main,但没有任何东西在它上面调用GetEnumerator(),然后在结果上调用MoveNext()…所以方法的主体永远不会被执行.
有关详细信息,请参见my article on iterator blocks,part two of Eric’s blog post或从home page of the first edition of C# in Depth下载第6章(第6章介绍迭代器块,并且是免费的).
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。