代码改变世界

C#中 类和结构 值类型和引用类型以及 值传递和引用传递

2012-01-30 22:42  javaspring  阅读(434)  评论(0编辑  收藏  举报

类:

   概念就不赘述了。

结构:

     1>它是从System.Object派生.但不能从别的类中派生,也不能从别的结构中继承.

     2>它是一个值类型.呵呵.

     3>里面还能写方法和字段,

    如:

   struct A{

       public int i;

       public int getMe()
       {
          return i;
       }

       A(int i )// KAO,构造函数.想不到.但是不能自己定义不含参数的....为毛....因为微软不调用,编译器会自动调用默认的构造函数,但是不会调用用户的..
       {//所以强制不允许用户定义这种.
          i = i;
       }
       public override string ToString()//重写了OBJECT的方法.
       {
          return i.ToString();
       }
 }
  4>看看下面的代码;

    A a = new A();//A a = new A(3);
    a.i = 7;//正确
    //////////////////////////

    A a;
    a.i = 7; //正确,这儿如果a 类的话就会出错,因为如果A 是类,那么a就是一个没有指向任何地方的地址.所以不能对它赋值.而A是结构,
             //堆栈中就有了个空间,所以可以直接赋值.
    int j = a.i;//错误,因为a只是在堆栈中有了个空间,但没有初始化它.

值类型:

   如int, short, double;等.对,还有结构.
   说的了,它就是一个值.
   不过记得这个词,"复制"!!!
   将一个值类型变量赋给另一个值类型变量时,是复制这个值!!记得是在栈中.


   引用MSDN上这样说的:

     值类型主要由两类组成:

        结构

        枚举

     结构分为以下几类:

        Numeric(数值)类型

        整型

       浮点型

       decimal

        bool

        用户定义的结构。

////

      引用类型:

      实体存放在堆中,但在区域栈中有一个引用(4个字节大小).
      出了这个区域这个引用就会OVER,但实体还在存活着,要等着GC去REALSE它.
      不过如果在出这个区域后.还有另一个引用指向它.GC也不会来处理它.
      //用一个网友的话来说.//////////

     StringBuilder strb = new StringBuilder();
     StringBuilder strb2 = strb;
则在堆中只有一个堆中对象,只是栈中有两个栈中对象指向堆中对象。
////////////////////////////////

     值传递和引用传递:

     明白了引用类型和值类型是怎么回事,值传递和引用传递也就不难理解,对吧?

     没有ref和out出现时都是值传递.

///再用这个网友的例子

     值传递:传的是对象的值拷贝。(即函数内参数对象是调用时传递的对象的栈中对象的拷贝。)
     引用传递:传的是栈中对象的地址。(即函数内参数对象与调用时传递的对象完全是同一栈中对象。)
现在用例子来说明传值跟传地址的不同:

private void button2_Click(object sender, System.EventArgs e)
{
     StringBuilder strb1 = new StringBuilder();
     StringBuilder strb2 = new StringBuilder();
     Test1(strb1);
     Test2(ref strb2);
     string str1 = strb1.ToString(); //str1值:"A"
     string str2 = strb2.ToString(); //str2值:"BC"
}

void Test1(StringBuilder strb)
{//strb和strb1是两个栈中对象,但指向相同的地址,这个操作是改变堆中对象
     strb.Append("A");

      //这里将strb指向一个新的堆中对象,所以后面的操作与strb1指向的栈中对象无关
     strb = new StringBuilder("B");
     strb.Append("C");
}

void Test2(ref StringBuilder strb)
{    //这里的strb和strb2是同一个栈中对象,所以改变strb的值使其指向另一个对象也等于改变strb2
     strb = new StringBuilder("B");
     strb.Append("C");
}