事实证明这是个谎言,谎言和挑衅

但这不再重要,因为挑战已被接受。

免责声明
. . . .
训练
我们创建一个继承链。为简单起见,我们将使用无参数构造函数。在构造函数中,我们将显示有关调用它的对象的类型和标识符的信息。
public class A
{
public A()
{
Console.WriteLine($"Type '{nameof(A)}' .ctor called on object #{GetHashCode()}");
}
}
public class B : A
{
public B()
{
Console.WriteLine($"Type '{nameof(B)}' .ctor called on object #{GetHashCode()}");
}
}
public class C : B
{
public C()
{
Console.WriteLine($"Type '{nameof(C)}' .ctor called on object #{GetHashCode()}");
}
}
运行程序:
class Program
{
static void Main()
{
new C();
}
}
然后我们得到输出:
Type 'A' .ctor called on object #58225482
Type 'B' .ctor called on object #58225482
Type 'C' .ctor called on object #58225482
抒情离题
, . , . , . :
:
public A() : this() { } // CS0516 Constructor 'A.A()' cannot call itself
:
public A() : this(new object()) { }
public A(object _) : this(0) { }
public A(int _) : this() { } // CS0768 Constructor 'A.A(int)' cannot call itself through another constructor
删除重复的代码
添加一个助手类:
internal static class Extensions
{
public static void Trace(this object obj) =>
Console.WriteLine($"Type '{obj.GetType().Name}' .ctor called on object #{obj.GetHashCode()}");
}
我们替换所有构造函数
Console.WriteLine($"Type '{nameof(...)}' .ctor called on object #{GetHashCode()}");
上
this.Trace();
但是,该程序现在输出: 在我们的例子中,可以使用以下技巧。谁知道编译时间类型?编译器。它还根据这些类型选择方法重载。对于通用类型和方法,它也生成构造的实体。因此,我们通过重写Trace方法来返回正确的类型推断,如下所示:
Type 'C' .ctor called on object #58225482
Type 'C' .ctor called on object #58225482
Type 'C' .ctor called on object #58225482
public static void Trace<T>(this T obj) =>
Console.WriteLine($"Type '{typeof(T).Name}' .ctor called on object #{obj.GetHashCode()}");
访问基本类型构造函数
这就是反思的源泉。向扩展添加方法:
public static Action GetBaseConstructor<T>(this T obj) =>
() => typeof(T)
.BaseType
.GetConstructor(Type.EmptyTypes)
.Invoke(obj, Array.Empty<object>());
将属性添加到B和C 类型:
private Action @base => this.GetBaseConstructor();
在任何地方调用基类型构造函数
将构造函数B和C的内容更改为:
this.Trace();
@base();
现在输出看起来像这样:
Type 'A' .ctor called on object #58225482
Type 'B' .ctor called on object #58225482
Type 'A' .ctor called on object #58225482
Type 'C' .ctor called on object #58225482
Type 'A' .ctor called on object #58225482
Type 'B' .ctor called on object #58225482
Type 'A' .ctor called on object #58225482
更改基本类型构造函数的调用顺序
在类型A内,创建一个帮助程序类型:
protected class CtorHelper
{
private CtorHelper() { }
}
由于此处仅语义很重要,因此建议将类型构造函数设为私有。实例化没有任何意义。该类型仅用于区分类型A构造函数的重载和从其派生的重载。出于相同的原因,该类型应放在A内并使其受到保护。
将适当的构造函数添加到A,B和C:
protected A(CtorHelper _) { }
protected B(CtorHelper _) { }
protected C(CtorHelper _) { }
对于类型B和C,向所有构造函数添加调用:
: base(null)
结果,类应如下所示
internal static class Extensions
{
public static Action GetBaseConstructor<T>(this T obj) =>
() => typeof(T)
.BaseType
.GetConstructor(Type.EmptyTypes)
.Invoke(obj, Array.Empty<object>());
public static void Trace<T>(this T obj) =>
Console.WriteLine($"Type '{typeof(T).Name}' .ctor called on object #{obj.GetHashCode()}");
}
public class A
{
protected A(CtorHelper _) { }
public A()
{
this.Trace();
}
protected class CtorHelper
{
private CtorHelper() { }
}
}
public class B : A
{
private Action @base => this.GetBaseConstructor();
protected B(CtorHelper _) : base(null) { }
public B() : base(null)
{
this.Trace();
@base();
}
}
public class C : B
{
private Action @base => this.GetBaseConstructor();
protected C(CtorHelper _) : base(null) { }
public C() : base(null)
{
this.Trace();
@base();
}
}
输出为:
Type 'C' .ctor called on object #58225482
Type 'B' .ctor called on object #58225482
Type 'A' .ctor called on object #58225482
天真的Simpleton认为编译器作弊

了解结果
通过向Extensions添加方法:
public static void TraceSurrogate<T>(this T obj) =>
Console.WriteLine($"Type '{typeof(T).Name}' surrogate .ctor called on object #{obj.GetHashCode()}");
并在接受CtorHelper的所有构造函数中调用它,我们得到 以下输出:当然,根据基本/派生原理的构造函数的顺序没有改变。但是,由于通过调用客户端无法访问的助手构造函数进行了重定向,因此可用于承载语义负载的客户端代码可用的构造函数的顺序已更改。
Type 'A' surrogate .ctor called on object #58225482
Type 'B' surrogate .ctor called on object #58225482
Type 'C' .ctor called on object #58225482
Type 'A' surrogate .ctor called on object #58225482
Type 'B' .ctor called on object #58225482
Type 'A' .ctor called on object #58225482