Call Constructor Base after Code Execution

2020-06-07 07:39发布

Let say we have Class A and Class B. ClassB extends Class A. (ClassB : ClassA)

Now let's say that whenever I instantiate ClassB, I'd like to Run some Random code and only then call "base" to reach ClassA constructor.

Like:

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

In the programming language I usually work with, I can do that, by simply calling super() after Console.WriteLine(); But I cant make it in C#. Is there any other syntax or other way to do that?

9条回答
放我归山
2楼-- · 2020-06-07 08:13

Another hack if you can get away with calling a static method.

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;
    }
}
查看更多
贼婆χ
3楼-- · 2020-06-07 08:16

There's a hacky way of doing it using an instance variable initializer:

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

The less hacky way of doing it is to rethink how you construct a ClassB to start with. Instead of having clients call the constructor directly, provide a static method for them to call:

public static ClassB CreateInstance()
{
    Console.WriteLine("Before initialization stuff");
    return new ClassB();
}
查看更多
走好不送
4楼-- · 2020-06-07 08:18

Recently I ran into a scenario where I needed to calculate some logic before passing the result into base.

I could just do something like

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

}

But I find that to be ugly, and can get really long horizontally. So I opted instead to use Func Anonymous methods.

E.g. imagine you have a base class,

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

Now you inherit from that and want to do some logic to determine the sql query text,

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

}

In this way you can execute code before Base is called and (in my opinion) it's not really hacky.

查看更多
登录 后发表回答