当覆盖抽象方法并尝试调用我当前正在覆盖的基类方法时,我遇到了一个非常奇怪的问题。
//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 类型。
我错过了什么?
最佳答案
编辑:我发现了问题……具有讽刺意味的是,考虑到 this blog post,我对 Eric 的“心理调试”评论并没有那么遥远。 .这是一个简短但完整的程序,它将演示正在发生的事情......
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]);
}
}
这将打印“In MyOverride.Execute”,但*不会“打印”In SqlBulkInsertOperation.Execute”...因为该方法是使用迭代器 block 实现的。
当然,您可以更简单地证明这一点很多:
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 章介绍了迭代器 block ,并且是免费的)以获取更多详细信息。
关于c# - 使用 "base"关键字时基类方法中的代码不执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3825336/