了解c#中的引用行为

Gra*_*Fox 2 c#

我对以下代码有疑问:

    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" };
    }
Run Code Online (Sandbox Code Playgroud)

为什么我的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; }
}
Run Code Online (Sandbox Code Playgroud)

先感谢您

编辑:如果我建议您使用'ref'关键字,我会收到此错误:

Error   CS0206  A property or indexer may not be passed as an out or ref parameter
Run Code Online (Sandbox Code Playgroud)

Mar*_*der 6

在您的方法中,您创建一个全新的实例Description.对此实例的引用存储在本地变量中descrToChange.

descrToChange作为参数,是引用变量的副本msg.Description.内部的原始引用descrToChange将在您的方法中被覆盖,内部引用msg.Description保持不变.

*解决方案#1:使用已创建的实例*

一种解决方案可能是修改引用变量已指向的实例的成员.您不在方法中创建新实例,只需使用已存在的实例:

static void changeDescription(Description descrToChange)
{
    descrToChange.Key = 2;
    descrToChange.Value = "Foobar";
}
Run Code Online (Sandbox Code Playgroud)

*解决方案#2:使用父级修改其子级*

另一种解决方案可能是Message用作参数:

static void changeDescription(Message msg)
{
    msg.Description = new Description() { Key = 2, Value = "Foobar" };
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

changeDescription(msg);
Run Code Online (Sandbox Code Playgroud)

*解决方案#3:ref用于修改引用(在变量内)*

如果msg.Description是一个字段而不是一个属性,并且您想msg.Description通过该方法修改该引用,请使用ref.请注意:明智地使用此关键字:

static void changeDescription(ref Description descrToChange)
{
    descrToChange = new Description() { Key = 2, Value = "Foobar" };
}
Run Code Online (Sandbox Code Playgroud)

并调用此方法:

changeDescription(ref msg.Description);
Run Code Online (Sandbox Code Playgroud)

这只有在你的财产是一个领域时才有效,我不建议:

class Message
{
    public Description Description;
    public int ID { get; set; }
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)