在c#中理解值和引用

今天在写一个小代码时遇到一个问题:如何将一个dataTable中的一行拷贝到另外一个结构相同的dataTable中,如果直接采用如下方式就会报错:

            DataRow drGround = ds.Tables[0].Rows[0];
            dt.Rows.Add(drGround);(提示drGround已经属于另外一张表了)

正解:

            DataRow myDataRow = (DataRow)ds.Tables[0].Rows[0];
            DataRow drGround = dt.NewRow();
            drGround.ItemArray = myDataRow.ItemArray;           
            dt.Rows.InsertAt(drGround, 0);//插到指定位置和报表保持一致
      

 

事实上这就涉及到值和引用的概念了,因为dataRow是引用类型的。为加深理解我从网上找了一些资料并将他们给整理了一下,给我和需要的朋友一个方便!
不过呢,我现在还是一学生,如有高见请指教!

 

C# 支持两种类型:“值类型”和“引用类型”。

值类型,例如:int、float、bool之类的基础类型,以及用struct定义的类型,如:DateTime。除此外,如string,数组,以及用class定义的类型等都是引用类型。对于C#来说,很难罗列出所有类型进行一一分别,这需要自己在编码过程中进行分析总结。

       值类型与引用类型的区别在于值类型的变量直接包含其数据,而引用类型的变量则存储对象引用。对于引用类型,两个变量可能引用同一个对象,因此对一个变量的操作可能影响另一个变量所引用的对象。对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响另一个变量。

 不过,无论是对于值类型还是引用类型来说,对于其作为函数参数或者返回值的时候,都是容易犯错误的地方。

  对于值类型来说,当其作为函数参数的时候,希望在函数中被修改,那么直接如下操作是不能被修改的。

public void Increment( int i )
{
  i++;
}


  要想在函数中对传进去的参数做真正的修改,需要借助于ref这个关键字,那么正确的形式如下。

public void Increment( ref int i )
{
 i++;
}


  也就是说,如果需要在函数中对值类型参数进行修改,需要用ref或者out进行标识才能真正实现。
    而对于引用类型来说,当其作为函数参数的时候,它所遇到的情况恰恰与值类型相反,即不希望在函数中被修改,举例如下。

public void AddValue( MyType typValue )
{
 typValue.Count = typValue.Count + 15;
}


  由于对于引用类型对象来说,其的赋值操作只是对原有对象的引用,因此在函数对其修改,实际上是直接修改了原有对象数据,这是很多情况不希望发生的(这里例如对数组或者DataTable操作这类)。
     为了防止这种事发生,需要给此类型提供clone函数。例如对于如上的类型,可以入下实现。

public class MyType:ICloneable
{
 private int nCount = 0;
 public int Count
 {
  set{ nCount = value;}
  get{ return nCount;}
 }
 public MyType()
 {}
 public MyType( int Value)
 {
  nCount = Value;
 }

 #region ICloneable Members

 public object Clone()
 {
  // TODO: Add MyType.Clone implementation
  return new MyType( nCount );
 }

 #endregion
}


  那么在调用的时候,用当前的对象的clone作为参数即可。

  不过对于引用类型来说,提供一个clone函数不是一件容易的事情,尤其出现引用类型嵌套的时候,所以说去实现一个完全clone功能是件很费事又不讨好的活,这也就是在论坛中常说的深copy和浅copy的问题。话虽如此,如果对于前面所说的有个大概了解,相信实现也不是不可能。

   

 

你可能感兴趣的:(C#)