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