c# - 使用 "base"关键字时基类方法中的代码不执行

标签 c# inheritance rhino-etl

当覆盖抽象方法并尝试调用我当前正在覆盖的基类方法时,我遇到了一个非常奇怪的问题。

//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/

相关文章:

c# - 你如何在静态方法中模拟对象

c# - `使用 Parallel.ForEach 加速文件处理但无法按正确顺序返回

c++ - 类名没有命名模板继承的类型问题

c# - RhinoETL - 加入两个表作为输入,在输出时写入两个表

c# - Microsoft.SqlServer.Management.Smo 引用中未显示备份类

c++ - 如何消除这种与继承相关的代码异味?

C++如何使类类型更通用并将其用作一种接口(interface)

.NET ETL 流程

rhino-etl - 在 Rhino-Etl 中链接输入操作

c# - 在多个连接的情况下是延迟加载、急切加载还是显式加载?