class a { public static int A; static a() { A = b.B + 1; } } class b { public static int B = a.A + 1; static void Main(string[] args) { Console.WriteLine(a.A+"-------------"+b.B);
Console.ReadLine(); } }我弄来弄去总感觉是2---------------1啊
60分请高手指点!
Console.ReadLine(); } }我弄来弄去总感觉是2---------------1啊
60分请高手指点!
class a
{
public static int A;
static a()
{
A = b.B + 1;
}
}class b
{
public static int B = a.A + 1;//先执行到这里
//没有写静态构造函数,则先从静态变量构造开始
//B = a.A + 1,使用到a.A,则调用到a的静态构造函数,进而调用A = b.B + 1;此时b.B值为0,则A = 0+1,a.A = 1,返回a.A+1就是1+1,则b.B就是2
static void Main(string[] args)
{
Console.WriteLine(a.A + "-------------" + b.B);
Console.ReadLine(); }
}
static a() => A = b.B + 1;
public static int B =0 ; //a.A 为 1
public static int B = a.A + 1; 为 2 ;static int B = a.A + 1;
说明下: 编译器会对B赋两次值
静态变量初始化后怎么可能再次赋值么。b.B的构造是早于Main函数的。系统启动->找到带有static void Main签名的类,调用Main方法。
因为调用到这个类的方法,所以会先初始化类的静态变量,所以虽然系统是从Main开始,但需要先在这之前去实例化静态变量,b没有静态构造函数,则直接执行
B = a.A + 1;
此时,使用到a类型的静态变量,则去初始化a类型的所有静态变量,发现有静态构造函数,则转入静态构造函数中执行:
A = b.B + 1;
此时b的静态变量B已经成功的分配内存,按照.net数值类型的规则,初始化为默认值0.则此时
A = b.B + 1;
等效
A = 0 + 1; => A 就是 1
A分配构造完成,返回给上层调用处(为什么说调用呢?+实际也是个方法调用,双目运算符)
B = a.A + 1; => B = 1 + 1; B就是2
此时a.A和b.B都已经被访问过一次,所以都已经成功的构造初始化好。以后对这2个字段的访问,不会再次执行a的静态构造函数,也不会再次执行b.B的构造语句。所以不存在赋值2次的。不要误导楼主。
.class private auto ansi beforefieldinit b
extends [mscorlib]System.Object
{
.method private hidebysig specialname rtspecialname static void .cctor() cil managed
{
.maxstack 8
L_0000: ldsfld int32 a::A
L_0005: ldc.i4.1
L_0006: add
L_0007: stsfld int32 b::B
L_000c: ret
} .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: call instance void [mscorlib]System.Object::.ctor()
L_0006: ret
}
//Main
.method private hidebysig static void Main(string[] args) cil managed
{
.maxstack 8
//加载a.A
L_0000: nop
L_0001: ldsfld int32 a::A
L_0006: box int32
//从常量字符串池中创建字符串
L_000b: ldstr "-------------"
//加载b.B
L_0010: ldsfld int32 b::B
L_0015: box int32
//调用string.Concat将三个参数合并
L_001a: call string [mscorlib]System.String::Concat(object, object, object)
L_001f: call void [mscorlib]System.Console::WriteLine(string)
L_0024: nop
L_0025: call string [mscorlib]System.Console::ReadLine()
L_002a: pop
L_002b: ret
}
.field public static int32 B}
extends [mscorlib]System.Object
{
//cctor类型初始化器,是一个静态方法,无参数无返回值,不能直接调用,最多只有一个
.method private hidebysig specialname rtspecialname static void .cctor() cil managed
{
.maxstack 8//堆栈定义
L_0000: ldsfld int32 a::A//压栈a.A
L_0005: ldc.i4.1 //压栈数字 1
L_0006: add //调用add双目运算符
L_0007: stsfld int32 b::B//结果保存到b.B
L_000c: ret //调用结束
} //用户编写的构造函数,如果没编写,则此处为默认构造函数,最终没有调用过,因为类不是静态类,所以还是存在构造函数的。直接调用Main方法,此构造函数代码忽略
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: call instance void [mscorlib]System.Object::.ctor()
L_0006: ret
}
//Main
.method private hidebysig static void Main(string[] args) cil managed
{
.maxstack 8
//加载a.A
L_0000: nop
L_0001: ldsfld int32 a::A
L_0006: box int32
//从常量字符串池中创建字符串
L_000b: ldstr "-------------"
//加载b.B
L_0010: ldsfld int32 b::B
L_0015: box int32
//调用string.Concat将三个参数合并
L_001a: call string [mscorlib]System.String::Concat(object, object, object)
L_001f: call void [mscorlib]System.Console::WriteLine(string)
L_0024: nop
L_0025: call string [mscorlib]System.Console::ReadLine()
L_002a: pop
L_002b: ret
}
.field public static int32 B}
IL没怎么了解过。现学现卖,说错请楼下指正。