Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在代码执行后调用构造函数基_C#_Constructor - Fatal编程技术网

C# 在代码执行后调用构造函数基

C# 在代码执行后调用构造函数基,c#,constructor,C#,Constructor,假设我们有A类和B类。B类扩展了A类。(B类:A类) 现在让我们假设,每当我实例化ClassB时,我都希望运行一些随机代码,然后调用“base”到达ClassA构造函数 比如: 在我通常使用的编程语言中,我可以做到这一点,只需在Console.WriteLine()之后调用super();但我不能用C。有没有其他语法或其他方法可以做到这一点?C#不允许在构造函数体中调用基本构造函数,这与Java不同。使用C#无法做到这一点。最好的办法是将代码提取到父级中它自己的方法中,然后在准备好后从子级调用该

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

现在让我们假设,每当我实例化ClassB时,我都希望运行一些随机代码,然后调用“base”到达ClassA构造函数

比如:


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

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

使用C#无法做到这一点。最好的办法是将代码提取到父级中它自己的方法中,然后在准备好后从子级调用该方法。

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

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

    }

有一种使用实例变量初始值设定项的黑客方法:

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

如果你可以通过调用一个静态方法逃脱惩罚,那就是另一个黑客

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

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

我可以这样做

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

}
但我发现这很难看,而且在水平方向上会变得很长。所以我选择使用Func匿名方法

例如,假设你有一个基类

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

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

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

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

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

在C#中使用基构造函数是没有办法的。您可以在base方法中提取登录名,并使用base.method()调用它。您通常使用哪种语言?因为如果它是Java,你就错了-你也不能这样做…@JonSkeet我知道这很古老,但听起来像Python。如果认为你有权访问基类以使参数成为func,那么这可能会很牵强。继承基类并重载构造函数。这种方法的问题是继承者可以覆盖基类的初始化方式(如果有的话)。这是有问题的,因为类应该始终能够保护自己的不变量,尤其是当类被设计为可扩展时。
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);
    }
}
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