锁定老帖子 主题:C#静态变量的诡异与恶心
精华帖 (0) :: 良好帖 (2) :: 新手帖 (2) :: 隐藏帖 (2)
|
|
---|---|
作者 | 正文 |
发表时间:2008-12-29
-------楼主原文----------
对C#更加迷惑了。类A中静态构造函数调用得到的B.Y,居然是0。这是什么道理? ------------------------- 有这个结果是因为这时候B的构造函数还没有执行,C#是限制性静态字段的初始化就是程序的第17行,在执行17行的时候需要执行A的静态构造函数,在执行A的构造函数时,仍然是在初始化B的静态字段阶段,执行完了,才该执行B的构造函数。 仅此而已,在程序中这么用,是有坏味道的代码。 |
|
返回顶楼 | |
发表时间:2008-12-29
你的补习内容中加上一条,“在执行静态构造函数之前要先给静态字段赋值”,这样一切都就不奇怪了。
|
|
返回顶楼 | |
发表时间:2008-12-30
静态构造理论上讲就是启动时就构造好了。所以任意时刻引用,都是可以的。楼主为何困惑呢。
|
|
返回顶楼 | |
发表时间:2008-12-30
Magicloud 写道 静态构造理论上讲就是启动时就构造好了。所以任意时刻引用,都是可以的。楼主为何困惑呢。 如果是当成智力题的话,确实也没什么好困惑的。但是如果是开发软件,甚至需要团队合作的情况下。下面的代码就很噩梦了: using System; class A { public readonly static int X = 1 + B.Y; } class B { public readonly static int Y = 2 + C.Z + A.X; } class C { public readonly static int Z = A.X + 4; } class D { public readonly static int W = C.Z + B.Y + A.X; } class MainClass { public static void Main(string[] args) { Console.WriteLine("A.X={0}, B.Y={1}, C.Z={2}", A.X, B.Y, C.Z);// 请尝试注释掉这一行,D.W的结果又会不同 Console.WriteLine("D.W={0}", D.W); Console.ReadKey(); } } 主要是不同的先后调用有不同的静态结果,Main函数在类中和类外结果会有所不同,但是表面上代码的赋值是一样的,如果多绕几个弯子,多来几个类,只要是人类都会很晕,所以感觉在应用过程中有这样的功能不是很迷惑人类吗,但是一门设计好的语言又允许这种情况存在。 想从方法论(或编译原理?)层面分析自己又不够深度,自己的程序里是不会出现这样的代码了,除非有人出题目给你做不得不做以外 |
|
返回顶楼 | |
发表时间:2008-12-30
貌似C#中初始化一个类是先初始化它的静态变量,再调用它的静态构造函数
见:http://msdn.microsoft.com/zh-cn/library/aa645612(VS.71).aspx 不过不知道为什么B.Y一开始就被初始化为零了。见下面: using System; namespace StaticTest { class A { public static int X; static A() { Console.WriteLine("calling A construct.This time x="+X); Console.WriteLine("In A's construct: B.Y="+B.Y); Console.WriteLine("Before init x,x="+X); X = B.Y + 1; Console.WriteLine("end init x,x="+X); } } class B { public static int Y = A.X + 1; static B() { Console.WriteLine("calling B construct."); Y=A.X+1; Console.WriteLine("Y="+Y); } static void Main() { Console.WriteLine("X={0}, Y={1}", A.X, B.Y); Console.WriteLine(" Y={0}", B.Y); Console.WriteLine("---end program----"); } } } |
|
返回顶楼 | |
发表时间:2008-12-30
subwayline13 写道 不要用JAVA的思路带到C#里面来,一般C#里是这样滴 using System; class A { public const int X = 1 + B.Y; } class B { public const int Y = 2 + C.Z + A.X; } class C { public const int Z = A.X + 4; } class D { public const int W = C.Z + B.Y + A.X; } 如果你写成这样,C#编译器就给打住了,别写这么诡异的代码,呵呵。 const还是慎用,尤其是跨程序集调用的时候。 |
|
返回顶楼 | |
发表时间:2008-12-31
语言不是一个完美的东西,请慎用!
交叉引用是一种很不好的编程习惯!而且现实在完全可以避免,所以这个问题不存在!世界任何东西都不是完美的! |
|
返回顶楼 | |
发表时间:2008-12-31
这帖子居然还两票良好贴 。。。。
装个vs 文件夹里就附带有c# language specification 花上半个小时就能得到解答的疑惑 居然也能开个帖子讨论这么半天 |
|
返回顶楼 | |
发表时间:2008-12-31
C#的静态构造跟Java的static代码块是一回事。这是非常重要的OO特性,本身没什么好恶心的。
关于静态变量的初始化顺序问题,也不要觉得C#恶心,其实真正恶心人的是C++的全局变量【静态变量跟全局变量一回事,不过全局变量更恶心人,更容易冲突,更没有访问保护】初始化顺序。C#明确规定了初始化顺序,而C++的规定是:无规定,所以,你完全没有可以依赖的东西,导致你【迫使你】把全局变量都转换为函数,而函数返回一个静态变量,更恶心人的地方在于这个函数要实现为inline函数【Cpper一般都要这么干,否则对不起自己的帽子】的话,你知道你的编译器怎么对付返回静态变量的内联函数的吗?虽然标准规定了必须返回那个独一份的东西,可是就有编译器对于inline函数,各返回各的copy。 而初始化顺序问题一定要有一个规定,C#不过是一个规定而已,如果你觉得这个顺序不好,你给出一个更好的顺序,反正像C++这种鸵鸟式的方式绝对不是办法。 |
|
返回顶楼 | |
发表时间:2009-01-05
刚刚学编程,就把自己当大师了。知道anders是谁吗?
|
|
返回顶楼 | |