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

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

浏览 28309 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (2) :: 隐藏帖 (2)
作者 正文
   发表时间:2008-12-29  
-------楼主原文----------
对C#更加迷惑了。类A中静态构造函数调用得到的B.Y,居然是0。这是什么道理?
-------------------------
有这个结果是因为这时候B的构造函数还没有执行,C#是限制性静态字段的初始化就是程序的第17行,在执行17行的时候需要执行A的静态构造函数,在执行A的构造函数时,仍然是在初始化B的静态字段阶段,执行完了,才该执行B的构造函数。

仅此而已,在程序中这么用,是有坏味道的代码。
0 请登录后投票
   发表时间:2008-12-29  
你的补习内容中加上一条,“在执行静态构造函数之前要先给静态字段赋值”,这样一切都就不奇怪了。
0 请登录后投票
   发表时间:2008-12-30  
静态构造理论上讲就是启动时就构造好了。所以任意时刻引用,都是可以的。楼主为何困惑呢。
0 请登录后投票
   发表时间: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函数在类中和类外结果会有所不同,但是表面上代码的赋值是一样的,如果多绕几个弯子,多来几个类,只要是人类都会很晕,所以感觉在应用过程中有这样的功能不是很迷惑人类吗,但是一门设计好的语言又允许这种情况存在。

想从方法论(或编译原理?)层面分析自己又不够深度,自己的程序里是不会出现这样的代码了,除非有人出题目给你做不得不做以外

0 请登录后投票
   发表时间: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----");
          } 

      } 
0 请登录后投票
   发表时间: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还是慎用,尤其是跨程序集调用的时候。
0 请登录后投票
   发表时间:2008-12-31  
语言不是一个完美的东西,请慎用!
交叉引用是一种很不好的编程习惯!而且现实在完全可以避免,所以这个问题不存在!世界任何东西都不是完美的!
0 请登录后投票
   发表时间:2008-12-31  
这帖子居然还两票良好贴  。。。。
装个vs 文件夹里就附带有c# language specification  花上半个小时就能得到解答的疑惑  居然也能开个帖子讨论这么半天
0 请登录后投票
   发表时间:2008-12-31  
C#的静态构造跟Java的static代码块是一回事。这是非常重要的OO特性,本身没什么好恶心的。

关于静态变量的初始化顺序问题,也不要觉得C#恶心,其实真正恶心人的是C++的全局变量【静态变量跟全局变量一回事,不过全局变量更恶心人,更容易冲突,更没有访问保护】初始化顺序。C#明确规定了初始化顺序,而C++的规定是:无规定,所以,你完全没有可以依赖的东西,导致你【迫使你】把全局变量都转换为函数,而函数返回一个静态变量,更恶心人的地方在于这个函数要实现为inline函数【Cpper一般都要这么干,否则对不起自己的帽子】的话,你知道你的编译器怎么对付返回静态变量的内联函数的吗?虽然标准规定了必须返回那个独一份的东西,可是就有编译器对于inline函数,各返回各的copy。

而初始化顺序问题一定要有一个规定,C#不过是一个规定而已,如果你觉得这个顺序不好,你给出一个更好的顺序,反正像C++这种鸵鸟式的方式绝对不是办法。
0 请登录后投票
   发表时间:2009-01-05  
刚刚学编程,就把自己当大师了。知道anders是谁吗?
0 请登录后投票
论坛首页 编程语言技术版

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