簡體   English   中英

函數中類參數之間的差異

[英]difference between class parameter in function

我在Visual Studio中編寫了這段代碼。

public class Class1
 {
    public string MySTR;
 }


private static void func1(Class1 class )
 {
  class = new Class1();
  class.MySTR = "B";
 }

private static void func2(Class1 class )
{
  class.MySTR = "C";
}

static void Main(string[] args) 
{       
  Class1 class = new Class1();
  class.MySTR = "A";
  func1(class);
  Console.WriteLine(class.MySTR);
  func2(ref class);
  Console.WriteLine(class.MySTR);
}

我本來希望獲得AA,但是我獲得了AC。

這些方法之間有什么區別?

謝謝。

類別是參考類型,確定此代碼返回“ B”

using System;
namespace ConsoleApplication2
{
    public class Class1
    {
        public string MySTR;
    }
    class Program
    {
        private static void func1(Class1 c )
         {
          //c = new Class1();
          c.MySTR = "B";
         }

        private static void func2(Class1 c )
        {
          c.MySTR = "C";
        }

        static void Main(string[] args) 
        {       
          Class1  c = new Class1();
          c.MySTR = "A";
          func1(c);
          Console.WriteLine(c.MySTR);
          //func2(ref c);Error
          //Console.WriteLine(c.MySTR);
          Console.ReadKey();
        }
    }
}

為什么您期望獲得"AA" "AC"是正確的輸出。 檢查以下代碼塊中的注釋(對代碼進行了一些小的修改以使其可以編譯和運行):

private static void func1(Class1 class1)
{
    //create new instance of Class1
    class1 = new Class1();
    //modify the new instance. 
    //Original instance passed to method parameter remain untouched
    //Hence you still got "A" from 1st Console.WriteLine(class1.MySTR);
    class1.MySTR = "B";
}

private static void func2(Class1 class1)
{
    //modify Class1 instance passed to method parameter. 
    //It's MySTR member value becomes "C" after this
    //Hence you got "C" from 2nd Console.WriteLine(class1.MySTR);
    class1.MySTR = "C";
}

static void Main(string[] args)
{
    Class1 class1 = new Class1();
    class1.MySTR = "A";
    func1(class1);
    Console.WriteLine(class1.MySTR);
    func2(class1);
    Console.WriteLine(class1.MySTR);
}

是的,這是正確的,

當您通過ref傳遞時,它將傳遞地址並更新該地址上的值,以便其工作。

首先,您創建了一個對象,因此在堆上創建了一個對象,並為該對象分配了一個地址,並分配了MySTR =“ A”,因此,現在MySTR的值為A,現在您調用了函數1,它將進入帶有MySTR =“ A”的函數1,您在那里重新初始化了該對象,因此在不同的地址上創建了另一個對象,並且您已經分配了MySTR =“ B”的值,現在您嘗試打印cl.MySTR,其中該值A已經存儲,所以第一個輸出是A

在第二部分中,您已經傳遞了該對象的地址,並嘗試更改同一對象中的值,因此它將是C。

您的代碼應該看起來像

班級計划

{

    static void Main(string[] args)
    {
        Class1 cl = new Class1();
        cl.MySTR = "A";
        func1(cl);
        Console.WriteLine(cl.MySTR);
         func2(ref cl);
         Console.WriteLine(cl.MySTR);
         Console.ReadLine();
    }

    private static void func1(Class1 cla)
    {
        cla = new Class1();
        cla.MySTR = "B";
    }
    private static void func2(ref Class1 clas)
    {
        clas.MySTR = "C";
    }
}
public class Class1
{
    public string MySTR;

}

har07正確。

為了進一步說明,引用類型(例如類)始終在C#中通過引用傳遞。 我假設您來自C(++)背景,因此可以想象該函數實際上是func2(Class1 *class1)

ref關鍵字(必須同時存在於方法及其調用中,不能混用)將按引用傳遞引用,即。 func2(Class1 **class1) 這允許您返回一個新實例(您可能在func1嘗試這樣做的方式)。

另一方面,結構和其他值類型默認情況下按值傳遞,即。 func(Struct1 s) ref與結構一起使用會比較棘手,但實際上,它大多數都可以像func(Struct1 **s)一樣工作。 您可以將值分配給struct字段,並且可以傳回全新的結構“實例”。

另一個“按引用引用”變體是out關鍵字,它類似於對調用方的承諾-您不會傳遞現有引用,但是被調用方必須將引用傳遞回去:

void DoStuff(out int num)
{
  num = 23;
}

void SomeOtherFunction()
{
  int myNum;

  DoStuff(out myNum);

  // myNum now contains the value 23
}

myNum在調用之前具有的值無關緊要(在我的示例中,變量實際上是“未定義”的-通過ref或按值傳遞它會導致編譯器錯誤),並且被調用方( DoStuff必須分配其所有out參數返回之前。

這兩個方法被聲明為static ,這意味着它們是實例無關的 如果您在func1中更改它們,則將在Class1所有實例中更改它們

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM