繁体   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