熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

ASP.NET教程:Ref和Out關鍵字異同

2013-11-13 10:22:11  來源: .NET編程 

  類型介紹

  在幾乎所有的OOP語言中都存在種類型的值


    值類型
    引用類型

  以C#為例其值類型為sbytebytecharshortushortintuintlong和ulongfloat和double當然還有decimal和bool而引用類型則是string和object

  我想說的

  我想說的就是——Ref和Out把我弄糊塗的原因是當時沒有認真的去分析它對不同類型所做出的不同的動作

  對於值類型

  使用了Ref和Out的效果就幾乎和C中使用了指針變量一樣它能夠讓你直接對原數進行操作而不是對那個原數的Copy進行操作舉個小例子

  using System;namespace ConsoleApplication
{
     /// <summary>
     /// Class 的摘要說明
     /// </summary>
 class Class
 {
      /// <summary>
      /// 應用程序的主入口點
      /// </summary>
  [STAThread]
  static void Main(string[] args)
  {
       int a = ;
       int b;       squareRef(ref a);
       squareOut(out b);       ConsoleWriteLine(The a in the Main is: + a);
       ConsoleWriteLine(The b in the Main is: + b);
  }  static void squareRef(ref int x)
  {
       x = x * x;
       ConsoleWriteLine(The x in the squareRef is: + x);
  }  static void squareOut(out int y)
  {
       y = ;
       y = y * y;
       ConsoleWriteLine(The y in the squareOut is: + y);
  }
 }
}

  顯示的結果就是——

  這樣的話就達到了和C中的指針變量一樣的作用

  對於引用類型

  對於引用類型就比較難理解了

  先要了解到這一層——就是當一個方法接收到一個引用類型的變量的時候它將獲得這個引用(Reference)的一個Copy由於Ref關鍵字可以用來向方法傳遞引用所以如果這個功能被誤用了——比如當一個如數組類型的引用對象用關鍵字Ref傳遞的時候被調用的方法實際上已經控制了傳遞過來的引用本身這樣將使得被調用方法能用不同的對象甚至NULL來代替調用者的原始引用!

  

  如圖內存地址為的變量arrayA中其實存放著數組{……}的內存起始地址如果一個方法fun()使用fun( arrayA[] )的話它將順利的獲得數據但這個將放在一個Copy中不會放到內存的位置而這個時候我們如果使用fun( ref arrayA[] )的話我們得到的值就是啦(也就是說被調用方法能夠修改掉arrayA中的那個引用使之不再指向甚至可以用NULL來代替這樣的話那個地址中的數據可能就要被垃圾回收機制清理了

  有個例子

  using System;
using SystemDrawing;
using SystemCollections;
using SystemComponentModel;
using SystemWindowsForms;
using SystemData;

  namespace RefOut
{
 /// <summary>
 /// Form 的摘要說明
 /// </summary>
 public class Form : SystemWindowsFormsForm
 {
  private SystemWindowsFormsButton button;
  private SystemWindowsFormsLabel label;
  /// <summary>
  /// 必需的設計器變量
  /// </summary>
  private SystemComponentModelContainer components = null;

  public Form()
  {
   //
   // Windows 窗體設計器支持所必需的
   //
   InitializeComponent();

  //
   // TODO: 在 InitializeComponent 調用後添加任何構造函數代碼
   //
  }

  /// <summary>
  /// 清理所有正在使用的資源
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null)
    {
     componentsDispose();
    }
   }
   baseDispose( disposing );
  }

  #region Windows 窗體設計器生成的代碼
  /// <summary>
  /// 設計器支持所需的方法 不要使用代碼編輯器修改
  /// 此方法的內容
  /// </summary>
  private void InitializeComponent()
  {
   thisbutton = new SystemWindowsFormsButton();
   thislabel = new SystemWindowsFormsLabel();
   thisSuspendLayout();
   //
   // button
   //
   thisbuttonDock = SystemWindowsFormsDockStyleTop;
   thisbuttonLocation = new SystemDrawingPoint( );
   thisbuttonName = button;
   thisbuttonSize = new SystemDrawingSize( );

  ; thisbuttonTabIndex = ;
   thisbuttonText = 顯示輸出;
   thisbuttonClick += new SystemEventHandler(thisbutton_Click);
   //
   // label
   //
   thislabelLocation = new SystemDrawingPoint( );
   thislabelName = label;
   thislabelSize = new SystemDrawingSize( );
   thislabelTabIndex = ;
   thislabelText = label;
   //
   // Form
   //
   thisAutoScaleBaseSize = new SystemDrawingSize( );
   thisClientSize = new SystemDrawingSize( );
   thisControlsAdd(thislabel);
   thisControlsAdd(thisbutton);
   thisMaximizeBox = false;
   thisMinimizeBox = false;
   thisName = Form;
   thisText = Ref & Out;
   thisResumeLayout(false);

  }
  #endregion

  /// <summary>
  /// 應用程序的主入口點
  /// </summary>
  [STAThread]
  static void Main()
  {
   ApplicationRun(new Form());
  }

  private void button_Click(object sender SystemEventArgs e)
  {
   int[] firstArray = { };
   int[] firstArrayCopy = firstArray;

  thislabelText = Test Passing firstArray reference by value;
   thislabelText += \n\nContents of firstArray before calling FirstDouble:\n\t;
   
   for(int i = ;i < firstArrayLength; i++)
   {
    thislabelText += firstArray[i] + ;
   }

  FirstDouble(firstArray);

  thislabelText += \n\nContents of firstArray after calling FirstDouble\n\t;

  for(int i=;i<firstArrayLength;i++)
   {
    thislabelText += firstArray[i] + ;
   }

  if(firstArray == firstArrayCopy)
    thislabelText +=\n\nThe references refer to the same array\n;
   else
    thislabelText +=\n\nThe reference refer to different arrays\n;

  int[] secondArray = { };
   int[] secondArrayCopy = secondArray;
   
   thislabelText += \nTest passing secondArray reference by reference;
   thislabelText += \n\nContents of secondArray before calling SecondDouble:\n\t;

  for(int i=;i<secondArrayLength; i++)
   {
    thislabelText += secondArray[i] + ;
   }

  SecondDouble(ref secondArray);
   thislabelText +=\n\nContents of secondArray after calling SecondDouble:\n\t;
   
   for(int i=; i<secondArrayLength;i++)
   {
    thislabelText += secondArray[i] + ;
   }

  if(secondArray== secondArrayCopy)
    thislabelText += \n\nThe reference refer to the same array;
   else
    thislabelText += \n\nThe reference refer to different arrays;

  thislabelText += \n___________________heshi_________________\nsecondarray\n;

  for(int i = ;i<secondArrayLength;i++)
   {
    thislabelText += secondArray[i] + ;
   }
   thislabelText +=\nsecondarraycopy\n;
   for(int i=;i<secondArrayCopyLength;i++)
   {
    thislabelText += secondArrayCopy[i] + ;
   }

  }

  void FirstDouble(int[] array)
  {
   for(int i = ;i<arrayLength;i++)
    array[i] *= ;
   array = new int[] { };
  }

  void SecondDouble(ref int[] array)
  {
   for(int i=;i<arrayLength;i++)
   {
    array[i] *= ;

  }
   array = new int[] { };
  }
 }
}
運行後的結果是

  這個就說明了被調用的程序已經改變了原有的Reference

  

  總結

  總的說來Ref和Out這兩個關鍵字都能夠提供相似的功效其作用也很像C中的指針變量稍有不同之處是


    使用Ref型參數時傳入的參數必須先被初始化而Out則不需要對Out而言就必須在方法中對其完成初始化
    使用Ref和Out時都必須注意在方法的參數和執行方法時都要加Ref或Out關鍵字以滿足匹配
    Out更適合用在需要Return多個返回值的地方而Ref則用在需要被調用的方法修改調用者的引用的時候

From:http://tw.wingwit.com/Article/program/net/201311/13408.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.