论坛首页 编程语言技术论坛

C#静态变量的诡异与恶心

浏览 27422 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (2) :: 隐藏帖 (2)
作者 正文
   发表时间:2009-01-05  
mooniscrazy 写道

刚刚学编程,就把自己当大师了。知道anders是谁吗?


不就是开发delphi那个吗,borland传奇之类的,好像我接触最早的开发工具就是borland c++ (5.0?忘了 2000年的时候了), 那公司差不多已经倒闭了,拜托把这里帖子都看完再回复
0 请登录后投票
   发表时间:2009-01-06  
这不是bug,但是这种交互使用静态变量在实际项目开发中不可取,具体没什么难度,两个互相引用的静态变量只能调用对方一次,否则就是死环循,MS没这么傻
0 请登录后投票
   发表时间:2009-01-09  
我从听说static constructor到用它也就是20分钟。这个帖子真长。
0 请登录后投票
   发表时间:2009-01-12  
毫无意义的争论

0 请登录后投票
   发表时间:2009-01-13  
ulpyuoo 给的地址里面有句::

引用
如果类中包含用来开始执行的 Main 方法,则该类的静态构造函数将在调用 Main 方法之前执行。如果类包含任何带有初始值设定项的静态字段,则在执行该类的静态构造函数时,先要按照文本顺序执行那些初始值设定项。


这说明B.Y已经初始化为0。这时候不要去考虑Y = A.X + 1,这时A类可能还没构造捏, 所以Y=0就对了。给Y赋值0后,才去执行A类的静态构造,接着是B的静态构造。接着是main执行。

于是出现X=1,Y=2。

假设我们把main函数移到A类里,则结果是:X=2,Y=1。

0 请登录后投票
   发表时间:2009-01-13  
楼主的思维陷入了泥潭中。帮楼主清理一下。
在不考虑“人”的因素的情况下
1、语言规范指定的有问题么?如果有问题,问题在哪里?如果没问题,进入下一步。
2、C#的对规范的实现有问题么?同上
3、给出的例子,在C#的语法上有问题么?
经过以上清理,我得出的结论是:明知恶心的代码,却偏偏要用它的人有问题。
而在实际开发中,倒是有可能出现类似的情况,这也是楼主担忧的问题。
但活人不能被尿憋死,只要你知道问题在哪里,就总会有办法解决。
0 请登录后投票
   发表时间:2009-01-14  
 using System;

class A
{
    public static int X = B.Y + 1;
}
class B
{
    public static int Y = A.X + 2;
}

class MainClass
{
    public static void Main(string[] args)
    {   
        Console.WriteLine("A.X={1},B.Y={0}", B.Y, A.X);
		Console.Read();
    }   
}

把输出顺序改了一下,输出的是1,3。
using System;

class A
{
    public static int X = B.Y + 1;
}
class B
{
    public static int Y = C.Z + 2;
}
class C
{
    public static int Z = A.X + 3;
}

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);
		Console.Read();
    }   
}

尝试变为3各类输出,6,5,3.
using System;

class A
{
    public static int X = B.Y + 1;
}
class B
{
    public static int Y = C.Z + A.X;
}
class C
{
    public static int Z = A.X + 3;
}

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);
		Console.Read();
    }   
}

输出4,3,3.
using System;

class A
{
    public static int X = B.Y + 1;
}
class B
{
    public static int Y = A.X+C.Z ;
}
class C
{
    public static int Z = A.X + B.Y;
}

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);
		Console.Read();
    }   
}

输出1,0,0.
改为string类型
using System;

class A
{
    public static string X = B.Y + "A";
}
class B
{
    public static string Y = A.X+"B" ;
}
class C
{
    public static string Z = A.X + B.Y;
}

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);
		Console.Read();
    }   
}

可见编译器在检测到某个静态变量的自我引用时使用默认值不再向下进行运算,至于元素在内存里的操作流程得请会使sos得高人出来说一下,没想到楼主偾世了一下引来这么多愤世...
0 请登录后投票
   发表时间:2009-01-15  
你对c#有偏见,c#比java仅从设计上讲要好很多,你为什么对java不恶心?
0 请登录后投票
   发表时间:2009-01-15  
treenode 写道
你的问题就是不理解

引用
难道这个时候B还没出生,但是B.Y已经出生了


实际上编译器载入一个类的时候分两个步骤,1.将类加载到内存堆的某个位置,这个时候所有静态成员的值都是0或者null;2.如果该类定义了静态构造方法,则执行该方法。当你调用A的静态方法时,实际上编译器已经完成了第一步的动作,而第二步还没有完成,所以成员的值仍然是0。很正常的现象,有什么好诡异的?

你说C++不是,但不知道你说的是哪个C++编译器,我刚才用TC++试了试(现在手上只有这个),结果一样是1,2。


结合以上所说的,改成以下的代码就一目了然了:

using System;    
namespace StaticTest  
{  
    class A  
    {  
        public static int X;  
        static A()  
        {  
            Console.WriteLine("calling A");  
            Console.WriteLine("B.Y是:{0}",B.Y);  
            X = B.Y + 1;  
        } 
static void Main()  
        {  
            Console.WriteLine("X={0}, Y={1}", A.X, B.Y);  
        }  
    }  
    class B  
    {  
        public static int Y = A.X + 1;  
        static B()  
        {  
            Console.WriteLine("calling B");  
            Console.WriteLine("Y等于:{0}",Y);

        }  
       
    }  
}  
0 请登录后投票
   发表时间:2009-01-15  
试了下,Java也是一样的结果。
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics