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

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

浏览 27423 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (2) :: 隐藏帖 (2)
作者 正文
   发表时间:2008-12-27  
treenode 写道

你的问题就是不理解引用难道这个时候B还没出生,但是B.Y已经出生了实际上编译器载入一个类的时候分两个步骤,1.将类加载到内存堆的某个位置,这个时候所有静态成员的值都是0或者null;2.如果该类定义了静态构造方法,则执行该方法。当你调用A的静态方法时,实际上编译器已经完成了第一步的动作,而第二步还没有完成,所以成员的值仍然是0。很正常的现象,有什么好诡异的?你说C++不是,但不知道你说的是哪个C++编译器,我刚才用TC++试了试(现在手上只有这个),结果一样是1,2。



C++的:
#include <iostream>
using namespace std;

class A
{
    public:
        const static int X;
};

class B
{
    public:
        const static int Y;
};

const int A::X = B::Y+1;
const int B::Y = A::X+1;

int main()
{
    cout<<"A::X="<<A::X<<","<<"B::Y="<<B::Y<<endl;
    
    return 0;
}

结果是:
A::X=1,B::Y=2

C#的:
using System;

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

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

结果是:
A.X=2,B.Y=1

Java的结果倒是跟C#的一样。

怎么解释?
0 请登录后投票
   发表时间:2008-12-27   最后修改:2008-12-27
treenode 写道

你的问题就是不理解引用难道这个时候B还没出生,但是B.Y已经出生了实际上编译器载入一个类的时候分两个步骤,1.将类加载到内存堆的某个位置,这个时候所有静态成员的值都是0或者null;2.如果该类定义了静态构造方法,则执行该方法。当你调用A的静态方法时,实际上编译器已经完成了第一步的动作,而第二步还没有完成,所以成员的值仍然是0。很正常的现象,有什么好诡异的?你说C++不是,但不知道你说的是哪个C++编译器,我刚才用TC++试了试(现在手上只有这个),结果一样是1,2。


不过你的理解貌似很合理,学习了,谢谢先,但是上面的问题还是存在, 我先多查查资料看~~
0 请登录后投票
   发表时间:2008-12-27  
willzh 写道

C#的:
using System;

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

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

结果是:
A.X=2,B.Y=1

Java的结果倒是跟C#的一样。

怎么解释?



这种写法,A和B实际上是完全对称的。哪一个静态方法先被调用取决于主程序调用它们的顺序。
你可以把
Console.WriteLine("A.X={0},B.Y={1}", A.X, B.Y);

换一下顺序:
Console.WriteLine("B.Y={0},A.X={1}", B.Y, A.X);


看看会输出什么
0 请登录后投票
   发表时间:2008-12-27  
c#与java的不同之处 = c#的诡异与恶心

这都哪跟哪啊
0 请登录后投票
   发表时间:2008-12-27  
yyliuliang 写道

c#与java的不同之处 = c#的诡异与恶心

这都哪跟哪啊

C#与Java是一样“恶心”的,与C++的区别如下:

这个是C++的
#include <iostream>
using namespace std;
class A
{
    public:
         static int X;
};
class B
{
    public:
         static int Y;
};
int A::X = B::Y+1;
int B::Y = A::X+2;
int main()
{
    cout<<"A::X="<<A::X<<","<<"B::Y="<<B::Y<<endl;
    return 0;
}

结果是:
引用
A::X=1,B::Y=3


这个是C#的
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={0},B.Y={1}", A.X, B.Y);
    }   
}

结果是:
引用
A.X=3,B.Y=2


顺便把Java的也贴上来:
class StaticTest
{
	public static void main(String[] args){
		System.out.println("A.X="+Integer.toString(A.X)+","+"B.Y="+Integer.toString(B.Y));
	}
}
class A
{
	static int X = B.Y + 1;
}
class B
{
	static int Y = A.X + 2;
}

引用
A.X=3,B.Y=2


不过这个问题基本上就是不同的语言不同的实现,说来也许并不能说谁优谁劣吧。
0 请登录后投票
   发表时间:2008-12-27  
其实,想想还是有点恶心,不知何故
0 请登录后投票
   发表时间:2008-12-28  
C# 和 Java 大同小异, C++ 与他们小同大异

C#:
1. Console.WriteLine("X={0}, Y={1}", A.X, B.Y);
2. A.X
3. A.X = B.Y + 1;
4. B.Y
5. B.Y = A.X + 1;
6. A.X = 0;
7. B.Y = 0 + 1;
8. A.X = 1 + 1;
9. Console: X=2, Y=1
using System;

namespace StaticTest
{
    class A
    {
        public static int X;
        static A()
        {
            X = B.Y + 1;
        }
    }
    class B
    {
        public static int Y;
        static B()
        {
            Y = A.X + 1;
        }
        static void Main()
        {
            Console.WriteLine("X={0}, Y={1}", A.X, B.Y);
        }
    }
}



C++:
1.  const int A::X = B::Y + 1;
2.  B::Y
3.  B::Y = 0;
4.  A::X = 0 + 1;
5.  const int B::Y = A::X + 1;
6.  A::X
7.  A::X = 1;
8.  B::Y = 1 + 1;
9.  std::cout << "X=" << A::X << ", Y=" << B::Y;
10. A::X
11. A::X = 1;
12. B::Y
13. B::Y = 2;
14. Console: X=1, Y=2
#include <iostream>

class A
{
    public:
        const static int X;
};

class B
{
    public:
        const static int Y;
};

const int A::X = B::Y + 1;
const int B::Y = A::X + 1;

int main()
{
    std::cout << "X=" << A::X << ", Y=" << B::Y;
    return 0;
}



Java:
1. System.out.printf("X=%d, Y=%d", A.X, B.Y);
2. A.X
3. A.X = B.Y + 1;
4. B.Y
5. B.Y = A.X + 1;
6. A.X = 0;
7. B.Y = 0 + 1;
8. A.X = 1 + 1;
9. Console: X=2, Y=1
class A
{
    public static int X;
    static
    {
        X = B.Y + 1;
    }
}

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

public class StaticTest
{
    public static void main(String[] args)
    {
        System.out.printf("X=%d, Y=%d", A.X, B.Y);
    }
}
0 请登录后投票
   发表时间:2008-12-28  
    想一想社区之间无穷无尽的争论就是由这样的初学者的不明事理造成的,希望楼主好好回去看看书,再来说品评java与C#之间的不同,你的水平还不到评论二种语言的水平。
0 请登录后投票
   发表时间:2008-12-28  
chu888chu888 写道

&nbsp;&nbsp;&nbsp; 想一想社区之间无穷无尽的争论就是由这样的初学者的不明事理造成的,希望楼主好好回去看看书,再来说品评java与C#之间的不同,你的水平还不到评论二种语言的水平。

确实,无论Java和C#我都是个初学者,所以没有经验来评论两者。不过我也没有在评论两者孰优孰劣,现在倒是感觉两者都很恶心,C++让人舒服点(这个是主观偏见罢了)。说回来,C#总得来说还是清晰优雅的,不然我也不会想着去学用了(以前不这么认为,至少现在如此)。
为了避免争论,我看我还是把“恶心”的题目改了吧,加了个“静态变量”,应该合理多了吧。


subwayline13 写道

就算都Jave跟Ruby开发者比较多,也不能用这么诡异的方式黑C#吧。

PS:这样诡异代码一般在诡异的公司的诡异的面试题里才会出现,楼主是个诡异的人,鉴定完毕。

我确实是在做题目的时候发现的……并不是我想诡异,题目摆在那里木办法,你说恶心不恶心
0 请登录后投票
   发表时间:2008-12-28  
这似乎和鸡先有还是蛋先有一个道理 .
楼主你觉得呢 ?

如果鸡先有恶心 , 蛋先有就不恶心了 ?
0 请登录后投票
论坛首页 编程语言技术版

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