执行代码后调用构造函数库

假设我们有A类和B类.BlassB扩展了A类。(ClassB:ClassA)

现在让我们说每当我实例化ClassB时,我想运行一些随机代码,然后调用“base”来达到ClassA构造函数。

喜欢:

class ClassA { public ClassA() { Console.WriteLine("Initialization"); } } class ClassB : ClassA { public ClassB() //: base() { // Using :base() as commented above, I would execute ClassA ctor before // Console.WriteLine as it is below this line... Console.WriteLine("Before new"); //base() //Calls ClassA constructor using inheritance //Run some more Codes here... } } 

在我经常使用的编程语言中,我可以通过在Console.WriteLine()之后调用super() Console.WriteLine() 。 但我不能在C#中做到这一点。 有没有其他语法或其他方法可以做到这一点?

使用实例变量初始化器有一种hacky方式:

 using System; class ClassA { public ClassA() { Console.WriteLine("Initialization"); } } class ClassB : ClassA { private readonly int ignoreMe = BeforeBaseConstructorCall(); public ClassB() { } private static int BeforeBaseConstructorCall() { Console.WriteLine("Before new"); return 0; // We really don't care } } class Test { static void Main() { new ClassB(); } } 

不太常见的做法是重新思考如何构建一个ClassB 。 不是让客户端直接调用构造函数,而是为它们提供一个静态方法来调用:

 public static ClassB CreateInstance() { Console.WriteLine("Before initialization stuff"); return new ClassB(); } 

另一个优雅的解决方案是完全重新思考对象的构造方式。 在基类的construct函数中,您可以调用自己的construct函数,并以下列方式省略依赖的将来构造函数:

 public class ClassA { public ClassA() { Construct(); } public virtual void Construct() { Console.WriteLine("3"); } } public class ClassB : ClassA { public override void Construct() { Console.WriteLine("2"); base.Construct(); } } public class ClassC : ClassB { public override void Construct() { Console.WriteLine("1"); base.Construct(); } } 

另一个黑客,如果你可以逃脱调用静态方法。

 public class ClassA { public ClassA() { Debug.WriteLine("Call A Constructor"); } } public class ClassB:ClassA { public ClassB():this(aMethod()) { } private ClassB(object empty):base() { Debug.WriteLine("Class B Second Constructor"); } private static object aMethod() { Debug.WriteLine("Run me First"); return null; } } 

实际上,您可以:

 class Foo { public Foo(string s) { Console.WriteLine("inside foo"); Console.WriteLine("foo" + s); } } class Bar : Foo { public Bar(string s) : base(((Func)(delegate () { Console.WriteLine("before foo"); return "bar" + s; }))()) { Console.WriteLine("inside bar"); } } class Program { static void Main(string[] args) { new Bar("baz"); } } 

输出:

 before foo inside foo foobarbaz inside bar 

但如果有可能,我宁愿不使用这个技巧。

你不能用C#做到这一点。 你最好的办法是将代码提取到父母自己的方法中,然后在你准备好时从孩子那里调用它。

C#不允许在构造函数体内调用基础构造函数,这与Java不同。

你不能调用基础构造函数。 但另一件事是,当您声明派生类的对象时,将调用构造函数派生和基派。

  class ClassA { public ClassA() { Console.WriteLine("Initialization"); } } class ClassB : ClassA { public ClassB() //: base() { // Using :base() as commented above, I would execute ClassA ctor before // Console.WriteLine as it is below this line... Console.WriteLine("Before new"); //base() //Calls ClassA constructor using inheritance //Run some more Codes here... } } void main(string[] args) { ClassB b = new ClassB(); } 

最近我遇到了一个场景,我需要在将结果传递给base之前计算一些逻辑。

我可以做点什么

 public SomeConstructor: base(FlagValue == FlagValues.One || FlagValues.Two ? "OptionA" : "OptionB") { } 

但我觉得这很难看,水平可以长得很长。 所以我选择使用Func Anonymous方法。

例如,假设你有一个基类,

 public class SomeBaseClass { public SomeBaseClass(Func GetSqlQueryText){ string sqlQueryText = GetSqlQueryText(); //Initialize(sqlQueryText); } } 

现在你从中inheritance并想要做一些逻辑来确定sql查询文本,

 public class SomeSqlObject : SomeBaseClass { public SomeSqlObject(ArchiveTypeValues archiveType) : base(delegate() { switch (archiveType) { case ArchiveTypeValues.CurrentIssues: case ArchiveTypeValues.Archived: return Queries.ProductQueries.ProductQueryActive; case ArchiveTypeValues.AllIssues: return string.Format(Queries.ProductQueries.ProductQueryActiveOther, (int)archiveType); default: throw new InvalidOperationException("Unknown archiveType"); }; }) { //Derived Constructor code here! } } 

通过这种方式,您可以在调用Base之前执行代码,并且(在我看来)它并不是真正的hacky。

我有同样的问题。 如果您无法访问基类,我发现此解决方案是最好的。

 public class BaseClass { public BaseClass(string someValue) { Console.WriteLine(someValue); } } public class MyClass : BaseClass { private MyClass(string someValue) : base(someValue) { } public static MyClass GetNewInstance(string someValue, bool overrideValue = false) { if (overrideValue) { someValue = "42"; } return new MyClass(someValue); } }