C# 引用类型与值类型
我正在阅读C#中的结构和类,据我所知,结构是值类型,类是引用类型。但我对类对象作为参数传递给方法时的行为有点困惑 假设我有以下代码:C# 引用类型与值类型,c#,.net,oop,reference,C#,.net,Oop,Reference,我正在阅读C#中的结构和类,据我所知,结构是值类型,类是引用类型。但我对类对象作为参数传递给方法时的行为有点困惑 假设我有以下代码: public class Program { public static void Main(string[] args) { var program = new Program(); var person = new Person { Firstname = "Bob",
public class Program
{
public static void Main(string[] args)
{
var program = new Program();
var person = new Person
{
Firstname = "Bob",
};
Console.WriteLine(person.Firstname);
program.ChangeName(person);
Console.WriteLine(person.Firstname);
program.Kill(person);
Console.WriteLine(person.Firstname);
Console.Read();
}
public void ChangeName(Person p)
{
p.Firstname = "Alice";
}
public void Kill(Person p)
{
p = null;
}
}
当我将
Person
类的实例传递给Program.ChangeName()
并将Person.Firstname
的值更改为Alice
时,更改会反映在我的Program.Main()
中实例化的原始Person对象上,这正是我所期望的,p
参数是对person
的引用。但是,当我尝试将p
设置为null
时,似乎没有任何更改。这是为什么?您正在将引用的副本设置为null,这不会影响原始值
它类似于(在C++中)
引用实际上是按值传递的,您不能更改它。您可以更改其指向的对象的属性,但是:
ptr->Name = "Bob";
显然会影响原始对象。您正在将引用副本设置为null,这不会影响原始值 它类似于(在C++中) 引用实际上是按值传递的,您不能更改它。您可以更改其指向的对象的属性,但是:
ptr->Name = "Bob";
显然会影响原始对象。当您“按引用传递”时,实际上是在传递引用的副本,因此将引用设置为指向另一个对象(或null)不会影响原始引用。但是,如果通过取消引用指针副本来更改对象的属性,则调用方将看到这些更改
如果您想真正通过引用传递并使kill方法工作,可以添加ref
关键字:
public void Kill(ref Person p)
{
p = null;
}
当您“按引用传递”时,实际上是在传递引用的副本,因此将该引用设置为指向另一个对象(或null)不会影响原始引用。但是,如果通过取消引用指针副本来更改对象的属性,则调用方将看到这些更改
如果您想真正通过引用传递并使kill方法工作,可以添加ref
关键字:
public void Kill(ref Person p)
{
p = null;
}
参数Person p是对对象的引用。当您将其置零时-您只是将引用置零,而不是将对象置零。因为
p
是被调用方法的局部变量。您所做的只是将局部变量的引用改为null,而不是传入的person对象。C#中的所有参数都是按值传递的,除非它们特别标记为ref
或out
。对于结构,结构的全部内容是传递的值。如果对其进行修改,所做的更改不会影响原件,因为您修改了副本。对于类,只传递对对象的引用,但该引用是按值传递的。重新指定引用的副本不会影响原始副本。但是,您可以操作对象的内容,因为原始引用和复制的引用都指向同一对象。您只需将引用设置为null,而不更改现有引用处的数据。假设p是一个可以放置块的盒子。将p设置为null会将p中的块放在一边,但它不会对p中以前的块做任何操作。参数Person p是对对象的引用。当您将其置零时-您只是将引用置零,而不是将对象置零。因为p
是被调用方法的局部变量。您所做的只是将局部变量的引用改为null,而不是传入的person对象。C#中的所有参数都是按值传递的,除非它们特别标记为ref
或out
。对于结构,结构的全部内容是传递的值。如果对其进行修改,所做的更改不会影响原件,因为您修改了副本。对于类,只传递对对象的引用,但该引用是按值传递的。重新指定引用的副本不会影响原始副本。但是,您可以操作对象的内容,因为原始引用和复制的引用都指向同一对象。您只需将引用设置为null,而不更改现有引用处的数据。假设p是一个可以放置块的盒子。将p设置为null会将p中的块放在一边,但它不会对p中以前的块做任何处理。