微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

当重写一个抽象方法并尝试调用我目前正在覆盖的基类方法时,我发现了一个非常奇怪的问题.

//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] 举报,一经查实,本站将立刻删除。

相关推荐