РЕДАКТИРОВАТЬ: Я нашел проблему ... и по иронии судьбы, мой комментарий "Эрик отладки" для Эрика был не так уж далек, учитывая этот пост в блоге . Вот короткая, но полная программа, которая продемонстрирует, что происходит ...
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», но не будет «печатать» в 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()
для результата ... так что тело метода никогда не выполняется.
См. мою статью о блоках итераторов , часть вторая в блоге Эрика , или загрузите главу 6 с домашней страницы первого издания C # in Depth (глава 6 посвящена блокам итераторов и бесплатна) для более подробной информации по этому вопросу.