为什么课程不需要添加参考?

时间:2017-10-03 07:00:04

标签: c# asp.net

类可以从方法设置名称并保留值:example

Employeer e  = new Employeer()
SetName(e);

但是我们不需要在调用方法SetName(e)时添加ref 但是你需要添加一个字符串

string name = "";
SetName(ref name);

谁可以解释一下它的细节?感谢

3 个答案:

答案 0 :(得分:3)

这是改变变量值和改变引用类型对象状态之间的区别。

使用Employee,您正在执行后者。使用string,您正在做前者。

使用引用类型,将复制和传递对对象的引用。这就是您只需传递e即可更改员工姓名的原因。但是,如果您在方法中重新分配e该怎么办?

// in the method
e = null;

传入的e会成为null吗?不。这是因为您正在将复制的参考点转换为其他内容。它与您创建员工时的原始参考无关。

这与string相同,因为string也是引用类型。将传入的字符串更改为方法内的其他内容时:

myString = "hello";

此更改不会反映在方法之外。从理论上讲,你可以在方法中改变字符串的状态,它会反映在方法之外。但是,string是不可变的(不会暴露任何可以让你改变其状态的东西)。

当您向其添加ref时,可以执行此操作,因为它会传递引用您的对象的引用的引用。因此,您可以在方法内重新分配内容,并且更改将反映在外部。

答案 1 :(得分:1)

在C#中,string数据类型具有以下属性: •String是引用类型,但行为类似于值类型。 •字符串是不可变的,即每次更改字符串时,都会创建一个新字符串,并且引用变量会更改其对新创建的字符串的引用。

对象类型的引用变量总是通过引用传递(可能看起来很棘手,但如果继续阅读,你会得到它))。 但是在字符串的情况下,默认传递的引用变量是按值传递的(除非您明确使用了ref关键字)。 所以在以下情况中:

String hello = "Hello";
MyFunction(hello);

将在MyFucntion中创建一个新的引用变量,该变量引用与hello string相同的位置。但是当您在MyFucntion中更改hello函数时,实际上新创建的引用变量的内容将被更改。

void MyFuntion(String hello)
{
    //a new string will be created and the reference value of the 
    //local hello will be changed
    hello = "Bye";
}

让我们在另一个例子的帮助下了解更多细节: 请考虑以下代码:

内部主要:

//let's create a string and pass it to a function as value and reference type
String str = "Hello World";
StringRefernecePassedByValue(str, ref str);
//the reference that was passed by value is the one that is the actual reference
//other one was a new refernece variable that has a copy of the reference
Console.WriteLine("Actual String: " + str);

该函数名为:

//The body of the function
static void StringRefernecePassedByValue(String valStr,ref String refStr)
{
    //Both of the passed reference variable are pointing to the same location
    Console.WriteLine("Are equal?: " + ReferenceEquals(valStr, refStr));

    //let's change the strings
    valStr = "Hello1";//a new string is created and now the valStr refer to it
    refStr = "Hello2";//a new string is created and now the refStr refer to it

    //let's confirm the output
    Console.WriteLine("Passed by Value: " + valStr);
    Console.WriteLine("Passed by Reference: " + refStr);

    //now both are changed are are no more refering to the same location
    Console.WriteLine("Are equal?: " + ReferenceEquals(valStr, refStr));
}

输出结果为:

Are equal?: True
Passed by Value: Hello1
Passed by Reference: Hello2
Are equal?: False
Actual String: Hello2

现在让我们为用户定义的类型执行上述操作:

//a user defined datatype
class Student
{
    public String name { get; set; }
    public String cgpa { get; set; }
}

内部主要:

//let's observe in case of Custom type
Student student = new Student();
student.name = "Ali";
student.cgpa = "3.5";

ClassRefernecePassedByValue(student, ref student);
Console.WriteLine("Actual String: " + student.name);

要调用的函数:

//the body of function
static void ClassRefernecePassedByValue(Student valStd, ref Student refStd)
{
    //Both of the passed reference variable are pointing to the same location
    Console.WriteLine("Are equal?: " + ReferenceEquals(valStd, refStd));

    //let's change the objects
    valStd.name = "Joseph";//changing the object refered by valStd
    refStd.name = "Mick";//changing the object refered by refStd 

    Console.WriteLine("Passed by Value: " + valStd.name);
    Console.WriteLine("Passed by Reference: " + refStd.name);

    //now both are same
    Console.WriteLine("Are equal?: " + ReferenceEquals(valStd, refStd));
}

输出:

Are equal?: True
Passed by Value: Mick
Passed by Reference: Mick
Are equal?: True
Actual String: Mick

因此得出结论,传递给函数时对字符串的引用实际上创建了一个新的引用变量,该变量包含对另一个字符串引用变量的复制引用,但是当字符串是不可变类型时,因此当新引用变量指向的字符串发生更改时然后实际参考变量保持不变。 enter image description here

另外,为了进一步了解,您可以获得完整的代码here

答案 2 :(得分:0)

如果在方法调用期间没有使用ref关键字传递字符串,那么它会创建一个新的字符串实例,并在新的字符串实例上进行更改。在返回方法后,我们传递的字符串值不受影响