Tim*_*rdt 3 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
{
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,SqlBulkInsertOperation没有做我需要它做的事情,所以我需要在我通过覆盖它来调用Execute(rows)之前和之后做一些工作.但是不执行SqlBulkInsertOperation.Execute(Rows)中的代码.
在Visual Studio中的调试器中运行此代码时,调试器的代码未执行.当我将鼠标悬停在Visual Studio编辑器中的"base"上时,它知道基类的类型为SqlBulkInsertOperation.
我错过了什么?
Jon*_*eet 10
编辑:我发现了这个问题......具有讽刺意味的是,我对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]);
}
}
Run Code Online (Sandbox Code Playgroud)
这将打印"在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();
}
}
Run Code Online (Sandbox Code Playgroud)
什么都没有使用方法的返回值 - 它被传递回Main,但没有任何东西调用GetEnumerator()它,然后MoveNext()在结果...所以方法的主体永远不会被执行.
见我的迭代块文章,埃里克的博客文章的第二部分,或者从下载第6章中的首页第一的C#版详解(第6章介绍迭代块,并且是免费的)对更多细节.
这是我运行的代码:
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("base");
return null;
}
}
public class MyOverride : SqlBulkInsertOperation
{
public override IEnumerable<Row> Execute(IEnumerable<Row> rows)
{
Console.WriteLine("override");
base.Execute(rows);
return null;
}
}
static class P
{
static void Main()
{
var m = new MyOverride();
m.Execute(null);
}
}
Run Code Online (Sandbox Code Playgroud)
它运行良好; 它产生"覆盖"和"基础".
告诉你什么:修改我在这里发布的程序,以便它产生你遇到的问题,我们将分析它.当您无法真正看到存在问题的真实代码时,很难分析问题.
对我来说很好.您的代码需要一点点的清理 - 你确定你编译和执行这段代码,而不是调试代码的早期构建?
class Program
{
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("done");
return rows;
}
}
public class MyOverride : SqlBulkInsertOperation
{
public override IEnumerable<Row> Execute(IEnumerable<Row> rows)
{
return base.Execute(rows);
}
}
static void Main(string[] args)
{
var x = new MyOverride();
x.Execute(null);
}
}
Run Code Online (Sandbox Code Playgroud)