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

时间:2012-05-26 05:44:46

标签: c# constructor

假设我们有A类和B类.ClassB扩展了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...
    }
}

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

9 个答案:

答案 0 :(得分:25)

使用实例变量初始化器有一种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();
    }    
}

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

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

答案 1 :(得分:5)

如果你可以通过调用静态方法来解决另一个问题。

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;
    }
}

答案 2 :(得分:5)

另一个优雅的解决方案是完全重新思考对象的构造方式。在基类的构造函数中,您可以调用自己的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();
    }
}

答案 3 :(得分:2)

实际上,您可以:

class Foo
{
    public Foo(string s)
    {
        Console.WriteLine("inside foo");
        Console.WriteLine("foo" + s);
    }
}

class Bar : Foo
{
    public Bar(string s) : base(((Func<string>)(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

但是如果可能的话,我宁愿不使用此技巧。

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

    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();

    }

答案 7 :(得分:0)

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

我可以做一些像

这样的事情
public SomeConstructor: base(FlagValue == FlagValues.One || FlagValues.Two ? "OptionA" : "OptionB")
{

}

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

E.g。想象你有一个基类,

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

现在你继承了它,并希望做一些逻辑来确定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。

答案 8 :(得分:0)

我遇到了同样的问题。如果您无法访问基类,我发现这个解决方案是最好的。

System.Reflection.Assembly.LoadFrom("yourResourceAssemblyfullpath")