C#Static用法大汇总
2010-05-06 12:11:20| 分类: c# |字号 订阅
静态变量
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。
有时候,我们希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代码国家名称的变量。例子:
protected void Page_Load(object sender, EventArgs e)
{
//直接使用“类名.成员”的格式,不能使用“对象名.成员”的格式,这点与JAVA不一样,JAVA两种都可以使用
Response.Write(Chinese.Country);
}
class Chinese
{
public static string Country = "中国";
public void getCountry()
{
//类中的成员方法也可以直接访问静态成员变量
HttpContext.Current.Response.Write("你好!" + Country);
}
}
需要注意的是:不能把任何方法体内的变量声明为静态,如下面这样是不行的:
public void getCountry()
{
//类中的成员方法也可以直接访问静态成员变量
HttpContext.Current.Response.Write("你好!" + Country);
static int i = 1;
}
静态方法
我们有时也希望不必创建对象就可以调用某个方法,换句话说也就是使该方法不必和对象绑定在一起。要实现这样的效果,只需要在类中定义的方法前加上static关键字就可以了,我们称这种方法为静态成员方法,还可以在类的非静态成员方法中象访问其他静态方法一样去访问这个静态方法,例子:
protected void Page_Load(object sender, EventArgs e)
{
Chinese.getCountry();
}
class Chinese
{
public static void getCountry()
{
HttpContext.Current.Response.Write("你好!中国");
}
}
注意:在静态方法里只能直接调用同类中其他的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可以使用,而静态方法在使用前不用创建任何对象。
const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等。在多数情况下可以混用。
二者本质的区别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值。而static readonly是在运行时计算出其值的,所以还可以通过静态构造函数来赋值。
要理解static,就必须要先理解另一个与之相对的关键字,很多人可能都还不知道有这个关键字,那就是auto,其实我们通常声明的不用static修饰的变量,都是auto的,因为它是默认的,就象short和long总是默认为int一样;我们通常声明一个变量:
int a;
string s;
其实就是:
auto int a;
auto string s;
而static变量的声明是:
static int a;
static string s;
这样似乎可以更有利于理解auto和static是一对成对的关键字吧,就像private,protected,public一样;
对于static的不理解,其实就是对于auto的不理解,因为它是更一般的;有的东西你天天在用,但未必就代表你真正了解它;auto的含义是由程序自动控制变量的生存周期,通常指的就是变量在进入其作用域的时候被分配,离开其作用域的时候被释放;而static就是不auto,变量在程序初始化时被分配,直到程序退出前才被释放;也就是static是按照程序的生命周期来分配释放变量的,而不是变量自己的生命周期
C#静态变量使用 static 修饰符进行声明,在类被实例化时创建,通过类进行访问;不带有 static 修饰符声明的变量称做非静态变量。static变量在对象被实例化时创建,通过对象进行访问一个类的所有实例的同一C#静态变量都是同一个值,同一个类的不同实例的同一非静态变量可以是不同的值。静态函数的实现里不能使用非静态成员,如非静态变量、非静态函数等。
例子1:
Code
#region//类A B中都含有static变量 构造函数
class A
{
public static int X;
static A()
{
X = B.Y + 1;
}
//static void Main()
//{
// Console.WriteLine("X={0},Y={1}", A.X, B.Y);//x=2,y=1
// Console.ReadLine();
//}
}
class B
{
public static int Y = A.X + 1;
static B() { }
static void Main()
{
Console.WriteLine("X={0},Y={1}", A.X, B.Y);//x=1,y=2
Console.ReadLine();
}
}
#endregion
解释:程序入库Main()位于类B中,因此类B首先进行初始化,次序为 int Y, 在对Y的赋值中使用到了类A,所以跳转到类A中,同样类A中的成员进行初始化,自域X开始这里为0,到静态构造函数X=B.Y+1,此时B.Y=0,所以X=1;然后->public static int Y = A.X + 1; ---》 得出Y=2.
例子2.
Code
#region//类Class1中既有 static变量和构造函数也有非 static的构造函数
class Class1
{
public static int count = 0;
static Class1()
{
count++;
}
public Class1()
{
count++;
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Class1 c1 = new Class1();
Class1 c2 = new Class1();
Console.WriteLine(Class1.count);//Class1.count=3
Console.ReadLine();
}
}
解释:在 Class1 c1 = new Class1();实例化c1的时候,到Class1中实例化成员,次序是static变量,static构造函数,最后是非static构造函数;此时count=2;
在 Class1 c2 = new Class1(); 实例化c2时,因为static的变量,构造函数不再被执行,所以只执行非静态构造函数,所以这里count++一次;count=3.
C# static -静态方法与静态变量的用法
范例1:
using System;
namespace ConsoleApplication2
{
public class student
{
public int studentid;
public string name;
public static int count;
}
class Class1
{
static void Main(string[] args)
{
student mystudent=new student ();
mystudent.name="mary";
student.count ++;
student mystudent2=new student ();
mystudent2.name ="li ming";
student.count ++;
Console.WriteLine (student.count );
Console.WriteLine (mystudent.name );
Console.WriteLine (mystudent2.name );
}
}
}
个人总结:静态方法与静态变量要直接使用类名+静态成员名访问,非静态方法与静态变量要用类的实例+静态成员名来访问。
C#不允许声明函数体内的static变量
C#居然不支持在函数体内声明static变量,这真的是很古怪,难道一个static变量的就一定要让别人知道吗(至少会被类的其他成员知晓)?
下边的C#和C++的比较,很明显,C++在这一点上要合理很多,uniqueID这个不断递增、控制着唯一ID的重要变量,永远不会被类里的其他成员无意破坏掉,不知道为什么C#不允许这种“函数体内部的static变量“,狂汗……
//下面是C#代码,uniqueID_只能是类的静态成员//而不能是Foo()函数的函数体内静态成员class Foo {
public Foo()
{
id_ = ++ uniqueID_;
}
private static int uniqueID_ = 0;
private int id_;};
//下面是C++代码,uniqueID可以是函数体内的静态变量//这样,它仅在本函数体内可见。
class Foo
{
public: Foo()
{
static int uniqueID = 0;
id_ = ++ uniqueID;
}
private: int id_;
}
静态变量和私有变量的最主要的区别就在于:他们分配内存空间的方式不一样。
静态变量的内存是在程序开始执时变量就占用了内存,直到程序结束时变量才释放内存.
私有变量(或者说是局部变量,不知道你是不是指这个:)),是在程序运行到该步的时候分配内存。所以,当离开了该私有变量的作用域的时候,私有变量的内存空间会被释放。
所以:静态变量只的值只会初始化一次,后面每次访问,都是上次处理过的值,(即使是在一个函数内部)。 私有变量每次都初始化。
看下面的实践:
class Program
{
static void Main(string[] args)
{//输出未经定义的静态变量,结果为0;也说明了,在C#中未赋初值的变量系统自动赋为0
Console.WriteLine(sort.i);
//静态变量的访问方法(类名.静态变量名),而且还可以在外部操作静态变量呢,可见静态变量并不神秘;
sort.i = 5;
//输出5
Console.WriteLine(sort.i);
//还可以通过构造函数对静态变量初值呢,呵
sort sortTest = new sort();
//输出构造函数中的赋值 3;
Console.WriteLine(sort.i);
}
}
class sort
{
public static int i;
public sort()
{
i = 3;
}
}
总结:在类内部访问静态变量时,直接用静态变量名即可,不用以(类名.静态变量名),这样的方式访问,
除了有静态变量之外,还有静态类实例,还有静态方法.但用法都是大同小异;(没有静态类哦,呵呵越论越傻了)
如:public static void myFun(){} //静态方法
private static Random MyRandom=new Random(); //静态类实例
之所以有时声明为私有静态变量,是为了让它只初始化一次.这样节省了内存空间
但又想让它在外部是不可访问的,这样利用私有这个访问限定符就搞定了.
私有静态:安全又节省空间.
例:如果想在每次实例化类的时间生成一组随机数,但产生随机数是要用到一个类的,即Random,这个类不是静态类,它要产生实例,用产生的实例来生成随机数,但如果在每次类实例化时都产生一个Random实例,那内存空间简直是极大的浪费,所以可以用:
private static Random MyRandom=new Random();
这样每次类实例化时,都会用同一个Random实例MyRandom来产生随机数
静态方法:
静态方法是不属于特定对象的方法,静态方法可以访问静态成员变量,静态方法不可以直接访问实例变量,可以在实例函数调用的情况下,实例变量做为参数传给静态方法。静态方法也不能直接调用实例方法,可以间接调用,首先要创建一个类的实例,然后通过这一特定对象来调用静态方法。
实例方法:
一个实例方法的执行与特定对象关联,他的执行需要一个对象存在。实例方法可以直接访问静态变量和实例变量,实例方法可以直接访问实例方法、和静态方法,静态方法的访问方式为类名加点操作符加变量名。当多个实例对象存在时,内存中并不是存在某个特定的实例方法的拷贝,而是,相同类的所有对象都共享每个实例方法的一个拷贝(实例方法只占用“一套”空间)。
问题1:能不能用一个例子来说明,静态方法如何不可以直接访问实例变量,但可以在实例函数调用的情况下,实例变量做为参数传给静态方法?
例1:
class A
{
private int var1; -> 这是实例变量,有实例的时候才有她
public static GetRes()
{
return var1; // 调用静态方法的时候不需要类型实例,没有实例就没有var1,那么这里就不能访问实例变量var1
}
}
例2:
namespace cppShooter
{
public class A
{
public int x;
public int y;
public A() { }
public static int ADD(int a, int b)
{
// 不可以直接访问实例变量
// a = x;
return a + b;
}
}
public class B
{
public B()
{
A aClass = new A();
aClass.x = 10;
aClass.y = 5;
// 参数引用
Console.WriteLine(A.ADD(aClass.x, aClass.y));
}
}
}
静态方法是有类的时候就有的,没办法知道这个类有没有实例.也就是说,静态方法,并不知道实例变量是不是存在 ,当然就不能调用了
2.实例方法可以直接访问静态变量和实例变量
public class A
{
public int x;
public int y;
public A() { }
public void PopAdd()
{
// 直接引用静太方法
Console.WriteLine(ADD(x, y));
}
public static int ADD(int a, int b)
{
// 不可以直接访问实例变量
// a = x;
return a + b;
}
}
2010-05-06 12:11:20| 分类: c# |字号 订阅
静态变量
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。
有时候,我们希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代码国家名称的变量。例子:
protected void Page_Load(object sender, EventArgs e)
{
//直接使用“类名.成员”的格式,不能使用“对象名.成员”的格式,这点与JAVA不一样,JAVA两种都可以使用
Response.Write(Chinese.Country);
}
class Chinese
{
public static string Country = "中国";
public void getCountry()
{
//类中的成员方法也可以直接访问静态成员变量
HttpContext.Current.Response.Write("你好!" + Country);
}
}
需要注意的是:不能把任何方法体内的变量声明为静态,如下面这样是不行的:
public void getCountry()
{
//类中的成员方法也可以直接访问静态成员变量
HttpContext.Current.Response.Write("你好!" + Country);
static int i = 1;
}
静态方法
我们有时也希望不必创建对象就可以调用某个方法,换句话说也就是使该方法不必和对象绑定在一起。要实现这样的效果,只需要在类中定义的方法前加上static关键字就可以了,我们称这种方法为静态成员方法,还可以在类的非静态成员方法中象访问其他静态方法一样去访问这个静态方法,例子:
protected void Page_Load(object sender, EventArgs e)
{
Chinese.getCountry();
}
class Chinese
{
public static void getCountry()
{
HttpContext.Current.Response.Write("你好!中国");
}
}
注意:在静态方法里只能直接调用同类中其他的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可以使用,而静态方法在使用前不用创建任何对象。
const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等。在多数情况下可以混用。
二者本质的区别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值。而static readonly是在运行时计算出其值的,所以还可以通过静态构造函数来赋值。
要理解static,就必须要先理解另一个与之相对的关键字,很多人可能都还不知道有这个关键字,那就是auto,其实我们通常声明的不用static修饰的变量,都是auto的,因为它是默认的,就象short和long总是默认为int一样;我们通常声明一个变量:
int a;
string s;
其实就是:
auto int a;
auto string s;
而static变量的声明是:
static int a;
static string s;
这样似乎可以更有利于理解auto和static是一对成对的关键字吧,就像private,protected,public一样;
对于static的不理解,其实就是对于auto的不理解,因为它是更一般的;有的东西你天天在用,但未必就代表你真正了解它;auto的含义是由程序自动控制变量的生存周期,通常指的就是变量在进入其作用域的时候被分配,离开其作用域的时候被释放;而static就是不auto,变量在程序初始化时被分配,直到程序退出前才被释放;也就是static是按照程序的生命周期来分配释放变量的,而不是变量自己的生命周期
C#静态变量使用 static 修饰符进行声明,在类被实例化时创建,通过类进行访问;不带有 static 修饰符声明的变量称做非静态变量。static变量在对象被实例化时创建,通过对象进行访问一个类的所有实例的同一C#静态变量都是同一个值,同一个类的不同实例的同一非静态变量可以是不同的值。静态函数的实现里不能使用非静态成员,如非静态变量、非静态函数等。
例子1:
Code
#region//类A B中都含有static变量 构造函数
class A
{
public static int X;
static A()
{
X = B.Y + 1;
}
//static void Main()
//{
// Console.WriteLine("X={0},Y={1}", A.X, B.Y);//x=2,y=1
// Console.ReadLine();
//}
}
class B
{
public static int Y = A.X + 1;
static B() { }
static void Main()
{
Console.WriteLine("X={0},Y={1}", A.X, B.Y);//x=1,y=2
Console.ReadLine();
}
}
#endregion
解释:程序入库Main()位于类B中,因此类B首先进行初始化,次序为 int Y, 在对Y的赋值中使用到了类A,所以跳转到类A中,同样类A中的成员进行初始化,自域X开始这里为0,到静态构造函数X=B.Y+1,此时B.Y=0,所以X=1;然后->public static int Y = A.X + 1; ---》 得出Y=2.
例子2.
Code
#region//类Class1中既有 static变量和构造函数也有非 static的构造函数
class Class1
{
public static int count = 0;
static Class1()
{
count++;
}
public Class1()
{
count++;
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Class1 c1 = new Class1();
Class1 c2 = new Class1();
Console.WriteLine(Class1.count);//Class1.count=3
Console.ReadLine();
}
}
解释:在 Class1 c1 = new Class1();实例化c1的时候,到Class1中实例化成员,次序是static变量,static构造函数,最后是非static构造函数;此时count=2;
在 Class1 c2 = new Class1(); 实例化c2时,因为static的变量,构造函数不再被执行,所以只执行非静态构造函数,所以这里count++一次;count=3.
C# static -静态方法与静态变量的用法
范例1:
using System;
namespace ConsoleApplication2
{
public class student
{
public int studentid;
public string name;
public static int count;
}
class Class1
{
static void Main(string[] args)
{
student mystudent=new student ();
mystudent.name="mary";
student.count ++;
student mystudent2=new student ();
mystudent2.name ="li ming";
student.count ++;
Console.WriteLine (student.count );
Console.WriteLine (mystudent.name );
Console.WriteLine (mystudent2.name );
}
}
}
个人总结:静态方法与静态变量要直接使用类名+静态成员名访问,非静态方法与静态变量要用类的实例+静态成员名来访问。
C#不允许声明函数体内的static变量
C#居然不支持在函数体内声明static变量,这真的是很古怪,难道一个static变量的就一定要让别人知道吗(至少会被类的其他成员知晓)?
下边的C#和C++的比较,很明显,C++在这一点上要合理很多,uniqueID这个不断递增、控制着唯一ID的重要变量,永远不会被类里的其他成员无意破坏掉,不知道为什么C#不允许这种“函数体内部的static变量“,狂汗……
//下面是C#代码,uniqueID_只能是类的静态成员//而不能是Foo()函数的函数体内静态成员class Foo {
public Foo()
{
id_ = ++ uniqueID_;
}
private static int uniqueID_ = 0;
private int id_;};
//下面是C++代码,uniqueID可以是函数体内的静态变量//这样,它仅在本函数体内可见。
class Foo
{
public: Foo()
{
static int uniqueID = 0;
id_ = ++ uniqueID;
}
private: int id_;
}
静态变量和私有变量的最主要的区别就在于:他们分配内存空间的方式不一样。
静态变量的内存是在程序开始执时变量就占用了内存,直到程序结束时变量才释放内存.
私有变量(或者说是局部变量,不知道你是不是指这个:)),是在程序运行到该步的时候分配内存。所以,当离开了该私有变量的作用域的时候,私有变量的内存空间会被释放。
所以:静态变量只的值只会初始化一次,后面每次访问,都是上次处理过的值,(即使是在一个函数内部)。 私有变量每次都初始化。
看下面的实践:
class Program
{
static void Main(string[] args)
{//输出未经定义的静态变量,结果为0;也说明了,在C#中未赋初值的变量系统自动赋为0
Console.WriteLine(sort.i);
//静态变量的访问方法(类名.静态变量名),而且还可以在外部操作静态变量呢,可见静态变量并不神秘;
sort.i = 5;
//输出5
Console.WriteLine(sort.i);
//还可以通过构造函数对静态变量初值呢,呵
sort sortTest = new sort();
//输出构造函数中的赋值 3;
Console.WriteLine(sort.i);
}
}
class sort
{
public static int i;
public sort()
{
i = 3;
}
}
总结:在类内部访问静态变量时,直接用静态变量名即可,不用以(类名.静态变量名),这样的方式访问,
除了有静态变量之外,还有静态类实例,还有静态方法.但用法都是大同小异;(没有静态类哦,呵呵越论越傻了)
如:public static void myFun(){} //静态方法
private static Random MyRandom=new Random(); //静态类实例
之所以有时声明为私有静态变量,是为了让它只初始化一次.这样节省了内存空间
但又想让它在外部是不可访问的,这样利用私有这个访问限定符就搞定了.
私有静态:安全又节省空间.
例:如果想在每次实例化类的时间生成一组随机数,但产生随机数是要用到一个类的,即Random,这个类不是静态类,它要产生实例,用产生的实例来生成随机数,但如果在每次类实例化时都产生一个Random实例,那内存空间简直是极大的浪费,所以可以用:
private static Random MyRandom=new Random();
这样每次类实例化时,都会用同一个Random实例MyRandom来产生随机数
静态方法:
静态方法是不属于特定对象的方法,静态方法可以访问静态成员变量,静态方法不可以直接访问实例变量,可以在实例函数调用的情况下,实例变量做为参数传给静态方法。静态方法也不能直接调用实例方法,可以间接调用,首先要创建一个类的实例,然后通过这一特定对象来调用静态方法。
实例方法:
一个实例方法的执行与特定对象关联,他的执行需要一个对象存在。实例方法可以直接访问静态变量和实例变量,实例方法可以直接访问实例方法、和静态方法,静态方法的访问方式为类名加点操作符加变量名。当多个实例对象存在时,内存中并不是存在某个特定的实例方法的拷贝,而是,相同类的所有对象都共享每个实例方法的一个拷贝(实例方法只占用“一套”空间)。
问题1:能不能用一个例子来说明,静态方法如何不可以直接访问实例变量,但可以在实例函数调用的情况下,实例变量做为参数传给静态方法?
例1:
class A
{
private int var1; -> 这是实例变量,有实例的时候才有她
public static GetRes()
{
return var1; // 调用静态方法的时候不需要类型实例,没有实例就没有var1,那么这里就不能访问实例变量var1
}
}
例2:
namespace cppShooter
{
public class A
{
public int x;
public int y;
public A() { }
public static int ADD(int a, int b)
{
// 不可以直接访问实例变量
// a = x;
return a + b;
}
}
public class B
{
public B()
{
A aClass = new A();
aClass.x = 10;
aClass.y = 5;
// 参数引用
Console.WriteLine(A.ADD(aClass.x, aClass.y));
}
}
}
静态方法是有类的时候就有的,没办法知道这个类有没有实例.也就是说,静态方法,并不知道实例变量是不是存在 ,当然就不能调用了
2.实例方法可以直接访问静态变量和实例变量
public class A
{
public int x;
public int y;
public A() { }
public void PopAdd()
{
// 直接引用静太方法
Console.WriteLine(ADD(x, y));
}
public static int ADD(int a, int b)
{
// 不可以直接访问实例变量
// a = x;
return a + b;
}
}