我在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。
这些方法有什么区别?
谢谢。
答案 0 :(得分:0)
类是引用类型ok 此代码返回" B#34;
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();
}
}
}
答案 1 :(得分:0)
为什么你期望获得"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);
}
答案 2 :(得分:0)
是的,这是正确的,
当您通过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;
}
答案 3 :(得分:0)
har07说得对。
为了进一步说明,引用类型(例如类)总是通过引用在C#中传递。我假设你来自C(++)背景,所以想象一下这个函数实际上是func2(Class1 *class1)
。
ref
关键字(必须同时包含方法及其调用,不混合)将通过引用传递引用,即。 func2(Class1 **class1)
。这允许您返回一个新实例(您在func1
中尝试这样做的方式)。
另一方面,结构和其他值类型默认按值传递,即。 func(Struct1 s)
。在结构中使用ref
比较棘手,但实际上它大部分都像func(Struct1 **s)
一样工作,即。您可以为结构字段赋值,并且可以传回一个全新的结构“实例”。
另一个“引用引用”变体是out
关键字,类似于对调用者的承诺 - 您不传递现有引用,但被调用者必须传回引用:
void DoStuff(out int num)
{
num = 23;
}
void SomeOtherFunction()
{
int myNum;
DoStuff(out myNum);
// myNum now contains the value 23
}
myNum在调用之前的值无关紧要(在我的示例中,变量实际上是“未定义” - 通过ref
或按值传递会导致编译器错误)和被调用者({ {1}})必须在返回之前分配其所有DoStuff
参数。
答案 4 :(得分:-1)
这两种方法被声明为static
,这意味着它们是与实例无关的。如果您在func1中更改它们,则会在Class1