2009-01-01 22:50:16 duan2564 阅读数 46
  • C#系列课程面向对象篇

    这个是继《C#系列课程之基础知识入门篇》的篇,主要讲解的是C#中面向对象的有关知识,主要有类,接口,继承,多态,构造函数,析构函数,密封类,属性,抽象,结构体,枚举,静态类,部分类等等有关面向对象的专业知识。

    1621 人正在学习 去看看 徐新帅

今天看到了一个帖子题目说是"C#静态变量的诡异与恶心 "

我也说说我的看法,看下面的C#代码

   1. using System;  
   2.   
   3. namespace StaticTest  
   4. {  
   5.     class A  
   6.     {  
   7.         public static int X;  
   8.         static A()  
   9.         {  
  10.             X = B.Y + 1;  
  11.         }  
  12.     }  
  13.     class B  
  14.     {  
  15.         public static int Y = A.X + 1;  
  16.         static B()  
  17.         {  
  18.         }  
  19.         static void Main()  
  20.         {  
  21.             Console.WriteLine("X={0}, Y={1}", A.X, B.Y);  
  22.         }  
  23.     }  
  24. }  

 打印结果为X= 1 , Y= 2

第二个例子,java代码

   1. class StaticTest  
   2. {  
   3.     public static void main(String[] args){  
   4.         System.out.println(Integer.toString(A.X) +" "+Integer.toString(B.Y));  
   5.     }  
   6. }  
   7.   
   8. class A  
   9. {  
  10.     static int X = B.Y + 1;  
  11. }  
  12.   
  13. class B  
  14. {  
  15.     static int Y = A.X + 1;  
  16. }  
打印的结果为 2 1
结果看上去挺诡异的,其实还是需要分析一下
C#与java差不多,不分开讲
对于第一个例子,
1 在运行main之前,所有的变量进行默认初始化,X=0,Y=0
2 为了运行main方法,需要对类B进行静态初始化
3 B静态初始化,需要初始化静态变量Y
4 Y的初始化需要用到A的变量X,需要初始化类A
5 A的初始化时,又需要用到了Y变量,而此时类B早已经开始初始化,故不会再对B初始化,避免循环
6 直接取Y=0,得到X=1
7 然后返回后Y再被初始化为2
对于第二个例子
1 在运行main之前,所有的变量进行默认初始化,X=0,Y=0
2 由于需要调用A.X,故需要对A进行静态初始化
3 A中使用Y,对B进行初始化
4 B中又用到X,但由于A已经开始初始化,故不循环,直接取X=0,得到Y=1
5 然后得到X=2
 
2014-11-25 23:05:39 magic_fx 阅读数 310
  • C#系列课程面向对象篇

    这个是继《C#系列课程之基础知识入门篇》的篇,主要讲解的是C#中面向对象的有关知识,主要有类,接口,继承,多态,构造函数,析构函数,密封类,属性,抽象,结构体,枚举,静态类,部分类等等有关面向对象的专业知识。

    1621 人正在学习 去看看 徐新帅
using System;
class A
{
	public static int X;
	static A()
	{
		X=B.Y+1;
	}
}
class B
{
	public static int Y=A.X+1;
	static B(){}
	static void Main()
	{
		Console.WriteLine(“X={0},Y={1}”,A.X,B.Y);
	}
}
结果及原理
2008-04-15 11:25:00 hfzsjz 阅读数 5357
  • C#系列课程面向对象篇

    这个是继《C#系列课程之基础知识入门篇》的篇,主要讲解的是C#中面向对象的有关知识,主要有类,接口,继承,多态,构造函数,析构函数,密封类,属性,抽象,结构体,枚举,静态类,部分类等等有关面向对象的专业知识。

    1621 人正在学习 去看看 徐新帅

C#中是没有所谓的全局变量的.要构造出类的属性作为全局变量
例如:新建类GlobalParams
可以在类中这样写:
public static string user = ""; //定义变量
public GlobalParams ()
{
user ="abcd";//赋值构造
}
public string User
{
get
{
return user ;
}
set
{
user =value;
}

这样就可以其他窗体访问此User
MessageBox.Show (GlobalParams .User); //直接访问. 显示.结果:"abcd"

GlobalParams frm=new GlobalParams ();
frm.User="efg"; //修改该静态变量的值

MessageBox.Show (GlobalParams .User); //直接访问. 显示.结果:"efg"

2017-11-03 18:06:17 xxdddail 阅读数 5066
  • C#系列课程面向对象篇

    这个是继《C#系列课程之基础知识入门篇》的篇,主要讲解的是C#中面向对象的有关知识,主要有类,接口,继承,多态,构造函数,析构函数,密封类,属性,抽象,结构体,枚举,静态类,部分类等等有关面向对象的专业知识。

    1621 人正在学习 去看看 徐新帅

有时为了加快显示的速度,会将相对不变的数据给缓存起来。在缓存起来时,比较直接的方法是放到静态变量中。

在项目中,由于需要从服务器中捞起较多的数据,一般要3-5秒,网络稍慢的时候会更长时间。而每次显示界面时,都需要这么长的时间,显然是很不友好的。于是,就将这些数据放到了静态变量A中。而静态变量A又同时生成了一个菜单控件Menu1,在菜单控件Menu1的项目中响应其点击事件MenuItemClick。由于Menu1随同静态变量A一起,具有共同的生存期。但是显示的界面Form是每次都全新创建的,这样一来,第一次创建Form1使用的是静态变量A,每二创建Form2使用的依然是静态变量A。

而菜单事件MenuItemClick的响应由于每一次就已经放到了菜单项Menu1中,所以会随同Form1一起,MenuItemClick的响应动作自然的就会响应到Form1中,即更新到Form1的界面上。所以在再次创建Form产生Form2时,菜单项的MenuItemClick就会响应到Form1中而不会响应到Form2中。这样就产生了一个坑。

解决办法是,将变量A做成一个单例模式的类产生的实例,然后内部封装一个显示菜单的方法Show。再Show方法中传入菜单显示所需要的参数,同时再传入一个响应菜单事件MenuItemClick后再调用的方法,比如类型为Action<MyData>的action。MyData是MenuItemClick点击后收集到的数据。

这样一来,就可以确保每次都是同一个实例A,同时因为更新界面的行为是动态传入的,所以Form1和Form2在调用菜单显示时必须传入相应的更新行为Action<MyData>。

总结:当我们使用静态变量作为缓存时,一定要考虑好生存期和作用域,否则会造成莫名其妙的问题而难以查起。

2007-12-04 16:31:00 dql1982 阅读数 4733
  • C#系列课程面向对象篇

    这个是继《C#系列课程之基础知识入门篇》的篇,主要讲解的是C#中面向对象的有关知识,主要有类,接口,继承,多态,构造函数,析构函数,密封类,属性,抽象,结构体,枚举,静态类,部分类等等有关面向对象的专业知识。

    1621 人正在学习 去看看 徐新帅
 
  类的静态字段变量初始值设定项对应于一个赋值序列,这些赋值按照它们在相关的类声明中出现的文本顺序执行。如果类中存在静态构造函数则静态字段初始值设定项的执行在该静态构造函数即将执行前发生。否则,静态字段初始值设定项在第一次使用该类的静态字段之前先被执行,但实际执行时间依赖于具体的实现。在以下示例中:
using System;
class Test 

static void Main() {
     Console.WriteLine(
"{0} {1}", B.Y, A.X);
}

public static int F(string s) {
     Console.WriteLine(s);
     
return 1;
}

}

class A
{
public static int X = Test.F("Init A");
}

class B
{
public static int Y = Test.F("Init B");
}
或者产生如下输出:
Init A
Init B
1 1
或者产生如下输出:
Init B
Init A
1 1
这是因为 X 的初始值设定项和 Y 的初始值设定项的执行顺序无法预先确定,上述两种顺序都有可能发生;唯一能够确定的是:它们一定会在对那些字段的引用之前发生。但是,下面的示例:
using System;
class Test
{
static void Main() {
     Console.WriteLine(
"{0} {1}", B.Y, A.X);
}

public static int F(string s) {
     Console.WriteLine(s);
     
return 1;
}

}

class A
{
static A() {}
public static int X = Test.F("Init A");
}

class B
{
static B() {}
public static int Y = Test.F("Init B");
}

所产生的输出必然是:
Init B
Init A
1 1
  这是因为关于何时执行静态构造函数的规则规定B的静态构造函数以及B的静态字段初始值设定项必须在A的静态构造函数和字段初始值设定项之前运行。

C# 断点不赋值问题

阅读数 137

没有更多推荐了,返回首页