理解c#中的引用行为
本文关键字:引用 理解 | 更新日期: 2023-09-27 18:16:13
我有一个关于以下代码的问题:
static void Main(string[] args)
{
var msg = new Message()
{
Description = new Description() { Key = 1, Value = "Foo"},
ID = 1,
Name = "MyMessage"
};
changeDescription(msg.Description);
}
static void changeDescription(Description descrToChange)
{
descrToChange = new Description() { Key = 2, Value = "Foobar" };
}
为什么我的msg在方法调用后有Description (Key = 1, Value = "Foo") ?
类:
class Message
{
public Description Description { get; set; }
public int ID { get; set; }
public string Name { get; set; }
}
class Description
{
public int Key { get; set; }
public string Value { get; set; }
}
提前谢谢你
编辑:如果我使用'ref'关键字作为你的一些建议,我得到这个错误:
Error CS0206 A property or indexer may not be passed as an out or ref parameter
在您的方法中,您创建了一个全新的Description
实例。对该实例的引用存储在本地变量descrToChange
中。
descrToChange
作为参数,是引用变量msg.Description
的副本。descrToChange
内部的原始引用在您的方法中被覆盖,msg.Description
内部的引用保持不变。
*方案#1:使用已经创建的实例*
一个解决方案是修改引用变量已经指向的实例的成员。您不需要在方法中创建新实例,而只需使用已经存在的实例:
static void changeDescription(Description descrToChange)
{
descrToChange.Key = 2;
descrToChange.Value = "Foobar";
}
*解决方案#2:使用父节点来修改它的子节点*
另一个解决方案是使用Message
作为参数:
static void changeDescription(Message msg)
{
msg.Description = new Description() { Key = 2, Value = "Foobar" };
}
,并像这样命名:
changeDescription(msg);
*解决方案#3:使用ref
修改引用(在变量内)*
如果msg.Description
是一个字段而不是一个属性,并且您想通过方法修改msg.Description
中的引用,则使用ref
。注意:明智地使用这个关键字:
static void changeDescription(ref Description descrToChange)
{
descrToChange = new Description() { Key = 2, Value = "Foobar" };
}
,并使用:
changeDescription(ref msg.Description);
这只能在你的属性是一个字段的情况下工作,我不建议这样做:
class Message
{
public Description Description;
public int ID { get; set; }
public string Name { get; set; }
}
为什么我的msg后面有Description (Key = 1, Value = "Foo")方法调用吗?
因为你没有使用ref
关键字。
static void changeDescription(ref Description descrToChange)
{
descrToChange = new Description() { Key = 2, Value = "Foobar" };
}
你也必须改变你的方法调用如下:
changeDescription(ref msg.Description);
ref关键字导致参数通过引用传递,而不是通过价值。通过引用传递的效果是,对参数在被调用方法中反映在调用方法中。为例如,如果调用者传递一个局部变量表达式或数组元素访问表达式,被调用的方法替换对象ref形参引用的对象,然后是调用者的局部变量或数组元素现在指向新对象。
有关ref
关键字的更多信息,请查看此处。
现在让我们进一步了解它:
descrToChange = new Description() { Key = 2, Value = "Foobar" };
在上面的代码行中,我们创建了一个新的Description
对象并将其赋值给descrToChange
。但是,这个变量descrToChange
作为参数传递给方法,并且可以保存Description
类型对象的引用。我们可以传递一个Description
类型的对象给方法,然后改变它的数据,但是我们不能改变对这个对象的引用。如果这是您的意图,那么您应该通过引用传递参数。
您覆盖了引用。您可以更改现有的对象。
static void changeDescription(Description descrToChange)
{
descrToChange.Key = 2;
descrToChange.Value = "Foobar";
}