当前位置:  编程技术>.net/c#/asp.net

深入C#中静态成员和实例变量详解

    来源: 互联网  发布时间:2014-08-30

    本文导语:  在c#中,我们访问静态成员用的是类名+成员名称,而我们在访问实例成员的时候必须是对象名称+成员名称来进行访问。静态成员都是需要初始化的,即使你没有实例化对象也会被实例化,比如:   public static int count; 因为静态成...

在c#中,我们访问静态成员用的是类名+成员名称,而我们在访问实例成员的时候必须是对象名称+成员名称来进行访问。静态成员都是需要初始化的,即使你没有实例化对象也会被实例化,比如:
 

public static int count;

因为静态成员是CLR组织加载的。因此你不赋值,系统也会默认给你初始化,这里就是0了。而实例成员是在实例化对象后才被CLR加载的。

现在来看下副本的问题,当然就是存储的位置。那么什么是副本呢,MSDN里说的让人很难理解,因此我一开始根本不理解,总以为是有多个版本,但根本不是这个样子的。我们知道面向对象就是面向自然界的万物,那么一个类就是一个真实的存在。那么它就是一个原版咯,然后你建的每个对象就是他的实例,也就是他的一个副本。这样就好理解了。

如果多个人访问一个页面,那么将会实例化多个对象。而这多个对象虽然可能是一样的,但是在内存中存储的位置是不一样的,这样就做到了相互之间对象不会发生冲突。而静态变量则是不管你多少个来访问,他的值一旦初始化就不会改变,很多实例用的对象都是一致的,因此可以公用。我们再看,比如我实例化了一个对象,里面有静态成员,也有实例成员,但是你访问这个对象却不能访问静态成员。

那么静态成员是怎么访问的呢?我们知道,CLR在分配内存时,根据对象的大小在内存中划分一段区域,跟操作系统是相似的。CLR在加载程序时,发现编译器已经标记了这个静态变量,然后就在内存中这个应用程序域中分配出了一段区域来存储该静态变量,当然就是静态存储区了。因为这个静态变量存储在程序集的区域内,那么只要程序存在,即使这个类没有了,这个静态变量依然存在。然后在内存中也存在另一副本,起到引用的作用,当我们在访问该变量的时候,通过访问这个副本,然后副本指向这块内存区域位置。

实例成员的存储也是这样的,类在实例化一个对象的时候,就在内存中就会为其分配一段区域,以后每生成一个对象,就继续划分区域,一个接一个的排列。当我们访问里面的实例成员的时候就通过该对象来访问就可以了。

C#静态成员和实例成员

C#中类的成员要么是静态的,要么是非静态的。如果将类中的某个成员声明为static,则该成员是静态成员,否则为实例成员。

类的静态成员是属于类所有,不必产生类的实例就可以访问它(而且即便是产生了类的实例,也不能够通过该实例来访问类的静态成员),为类的所有实例所共享,无论这个类创建了多少个实例,一个静态成员在内存中只占有一块区域。

类的实例成员属于类的实例所有,每创建一个类的实例,都在内存中为实例成员开辟了一块区域。

例如:
 

代码示例:

using System;
public class StaticTest
{
  static int count;
  int number;

  public StaticTest()
  {
     count=count+1;
     number=count;
   }

  public void display()
  {Console.WriteLine("object={0}:count={1}",number,count);}
}

class MainTest
{  public static void Main()
   {  StaticTest a=new StaticTest();
      a.display();
      StaticTest b=new StaticTest();
      a.display();
      b.display(); }
}

运行结果:
  object=1:count=1
  object=1:count=2
  object=2:count=2

静态成员与实例成员

在类的成员的类型或者返回值类型前面加上关键字static,就能将该成员定义为静态成员(static member)。常量或类型声明会隐式地声明为静态成员,其他没有用static修饰的成员都是实例成员(instance member)或者称为非静态成员。静态成员属于类,被这个类的所有实例所共享;实例成员属于对象(类的实例),每一个对象都有实例成员的不同副本。

静态成员具有下列特征:
— 静态成员必须通过类名使用 . 运算符来引用,而不能用对象来引用。
— 一个静态字段只标识一个存储位置。无论创建了一个类的多少个实例,它的静态字段在内存中都只占同一块区域。
— 静态函数成员(方法、属性、事件、运算符或构造函数)不能作用于具体的实例,在这类函数成员中不能直接使用实例成员,必须通过类名来引用。

实例成员具有以下特点:
— 实例成员必须通过对象名使用 . 运算符来引用,而不能用类名来引用。
— 类的实例字段属于类的实例所有,每创建一个类的实例,都在内存中为实例字段开辟了一块区域。类的每个实例分别包含一组该类的所有实例字段的副本。
— 实例函数成员(方法、属性、索引器、实例构造函数或析构函数)作用于类的给定实例,在它们的代码体内可以直接引用类的静态和实例成员。

其实,我们在前面的几章中大量使用的Console类的WriteLine等方法都是静态方法,都是通过类名Console来引用的。

理解下面的代码,体会静态成员和实例成员的使用方法:
 

代码示例:

class Test
{
    int x;    // 实例字段
    static int y;  // 静态字段
    void F()   // 实例方法
    {
        x = 1;  // 正确:实例方法内可以直接引用实例字段
        y = 1; // 正确:实例方法内可以直接引用静态字段
    }

    static void G() // 静态方法
    {
        x = 1;   // 错误:静态方法内不能直接引用实例字段
        y = 1;   // 正确:静态方法可以直接引用静态字段
    }

    static void Main()       // 静态方法
    {

        Test t = new Test();  // 创建对象
        t.x = 1;           // 正确:用对象引用实例字段
        t.y = 1;           // 错误:不能用对象名引用静态字段
        Test.x = 1;        // 错误:不能用类名引用实例字段
        Test.y = 1;       // 正确:用类名引用静态字段
        t.F();    // 正确:用对象调用实例方法
        t.G();   // 错误:不能用对象名调用静态方法
        Test.F(); // 错误:不能用类名调用实例方法
        Test.G();  // 正确:用类名调用静态方法
    }
}

注意:上述代码中,Main也是Test类的静态方法,可以在其中直接使用静态成员,而不需要使用类名来引用。

以下代码演示了静态字段的性质:
 

代码示例:

// StaticMember.cs
// 静态字段的例子
using System;
public class Count
{
    static int count;
    int number;
    public Count()
    {
        count = count + 1;
        number = count;
    }

    public void show()
    {
        Console.WriteLine("object{0} : count={1}", number, count);
    }
}
class Test
{
    public static void Main()
    {
        Count a = new Count();
        a.show();
        Console.WriteLine("-----------------");
        Count b = new Count();
        a.show();
        b.show();
        Console.WriteLine("-----------------");
        Count c = new Count();
        a.show();
        b.show();
        c.show();
   }
}

输出结果:
 

object1 : count=1
-----------------
object1 : count=2
object2 : count=2
-----------------
object1 : count=3
object2 : count=3
object3 : count=3

说明:
类的所有实例的静态字段count的值都是相同的,一个实例改变了它的值,其他实例得到的值也将随之变化,说明所有实例都使用同一个count字段;而每个实例的成员字段number的值都是不同的,也不能被其他的实例化改变。

关于C#类的静态成员与实例变量的内容,就介绍这些吧,希望对大家有所帮助。


    
 
 

您可能感兴趣的文章:

  • 深入C#任务管理器中应用程序选项隐藏程序本身的方法详解
  • 深入C# 内存管理以及优化的方法详解
  • 深入c# Func委托的详解
  • C# 多态性的深入理解
  • 深入C#中使用SqlDbType.Xml类型参数的使用详解
  • 深入C# winform清除由GDI绘制出来的所有线条或图形的解决方法
  • 深入Unix时间戳与C# DateTime时间类型互换的详解
  • C# interface与delegate效能比较的深入解析
  • C#中IList<T>与List<T>的区别深入解析
  • 深入分析C#中WinForm控件之Dock顺序调整的详解
  • C#中静态的深入理解
  • C#泛型约束的深入理解
  • C#之CLR内存深入分析
  • 深入解析c#中枚举类型的定义与使用
  • 深入c#绘制验证码的详解
  • 深入c# 类和结构的区别总结详解
  • 深入c# GDI+简单绘图的具体操作步骤(一)
  • 深入探讨C#中的结构struct
  • 深入理解C# abstract和virtual关键字
  • c#方法中调用参数的值传递方式和引用传递方式以及ref与out的区别深入解析
  • 深入探讨C语言中局部变量与全局变量在内存中的存放位置 iis7站长之家
  • 从汇编看c++中变量类型的深入分析
  • 深入ORACLE变量的定义与使用的详解
  • 深入uCOS中全局变量的使用详解
  • 深入理解final变量的初始化
  • 解析VC中创建DLL,导出全局变量,函数和类的深入分析
  • 用32位int型变量表示单引号括起来的四个字符的深入探讨
  • 深入探讨C语言中局部变量与全局变量在内存中的存放位置
  • 深入浅出Shell编程 Shell变量介绍
  • PHP面向对象之旅:深入理解static变量与方法
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • java 静态代理 动态代理深入学习
  • 全局静态存储区、堆区和栈区深入剖析
  • 深入理解c# static 静态数据成员和方法
  • 深入理解C++的动态绑定与静态绑定的应用详解
  • 深入C#实例成员和静态成员详解
  • C++ 类的静态成员深入解析
  • 深入探讨Linux静态库与动态库的详解(一看就懂)
  • Java UrlRewriter伪静态技术运用深入分析
  • 深入解析java中的静态代理与动态代理
  • Docker支持更深入的容器日志分析
  • 关于《深入浅出MFC》
  • Linux有没有什么好的高级的书,我要深入,
  • 深入理解linux内核
  • [100分]有没有关于binutils的深入的资料?或者深入底层的资料?
  • 深入理解PHP内核 TIPI
  • 想深入学习Java应该学习哪些东西
  • 哪位有《JSP深入编程》电子版?
  • 想要深入学习LINUX该学什么?
  • 100分求:哪儿有《深入理解linux内核》可供下哉!
  • 如何深入Linux的内核学习?
  • U-BOOT得掌握到什么程序,用不用深入去学
  • 想深入了解操作系统该怎么做
  • 前一阵子学习了shell脚本,如果想深入点了解linux可以看什么书呢
  • 问一个《深入理解计算机系统》中的问题
  • 深入多线程之:深入分析Interlocked
  • ##想买书深入学习linux下的编程,请指教
  • 深入JDBC sqlserver连接写法的详解
  • 深入oracle特定信息排序的分析
  • 深入分析C中不安全的sprintf与strcpy
  • 哪儿有下载《深入理解Linux内核》这本书?(中文)


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3