为什么 C# 12 中的主构造函数以相反的顺序执行?
至少可以说,这是一个“突破性的改变”...... 示例:
namespace Whatever;
[TestClass]
public class UnitTestTemp
{
[TestMethod]
public void TestMethod1() // PASS // is expected, 1st is 1, 2nd is 2
{
using var stream = new MemoryStream(new byte[] { 1, 2, 3, 4 });
var classicDerived = new ClassicDerived(stream);
Console.WriteLine(classicDerived.Value1);
Console.WriteLine(classicDerived.Value2);
Assert.AreEqual(1, classicDerived.Value1);
Assert.AreEqual(2, classicDerived.Value2);
}
[TestMethod]
public void TestMethod2() // FAIL // is opposite, 1st is 2, 2nd is 1
{
using var stream = new MemoryStream(new byte[] { 1, 2, 3, 4 });
var primaryDerived = new PrimaryDerived(stream);
Console.WriteLine(primaryDerived.Value1);
Console.WriteLine(primaryDerived.Value2);
Assert.AreEqual(1, primaryDerived.Value1);
Assert.AreEqual(2, primaryDerived.Value2);
}
}
经典构造函数:
public class ClassicBase
{
public readonly int Value1;
protected ClassicBase(Stream stream)
{
Value1 = stream.ReadByte();
}
}
public class ClassicDerived : ClassicBase
{
public readonly int Value2;
public ClassicDerived(Stream stream) : base(stream)
{
Value2 = stream.ReadByte();
}
}
主构造函数:
public class PrimaryBase(Stream stream)
{
public readonly int Value1 = stream.ReadByte();
}
public class PrimaryDerived(Stream stream) : PrimaryBase(stream)
{
public readonly int Value2 = stream.ReadByte();
}
第一次测试结果:
TestMethod1
Source: UnitTestTemp.cs line 7
Duration: 4 ms
Standard Output:
1
2
第二次测试结果:
TestMethod2
Source: UnitTestTemp.cs line 21
Duration: 26 ms
Message:
Assert.AreEqual failed. Expected:<1>. Actual:<2>.
Stack Trace:
UnitTestTemp.TestMethod2() line 30
RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Standard Output:
2
1
如您所见,如果您在构造函数中使用流,就会有点问题。问题:
除了恢复到经典构造函数之外,还有其他方法可以解决这个问题吗?
(正在考虑类似
SetsRequiredMembers的新 required 修饰符)
在 Classic 类中,您在构造函数中进行初始化,而在 Primary 类中,您在初始值设定项中进行初始化。而且构造函数和初始化器的执行顺序确实是不同的。这与主构造函数无关。
如果您使用初始值设定项而不涉及主构造函数,则会得到相反的顺序。
我的设置截然不同。这是我的助手类:
static class Values
{
private static int n = 0;
public static int GetNext(string name)
{
n++;
Console.WriteLine($"{name}: {n}");
return n;
}
}
经典的类层次结构:
public class ClassicBase
{
public readonly int Value1 = Values.GetNext(nameof(Value1));
}
public class ClassicDerived : ClassicBase
{
public readonly int Value2 = Values.GetNext(nameof(Value2));
}
测试
var obj = new ClassicDerived();
Console.ReadKey();
打印:
Value2: 1
Value1: 2