C# 理解c语言中的引用行为#

C# 理解c语言中的引用行为#,c#,C#,我对以下代码有疑问: static void Main(string[] args) { var msg = new Message() { Description = new Description() { Key = 1, Value = "Foo"}, ID = 1, Name = "MyMessage" }; changeDescript

我对以下代码有疑问:

    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在方法调用后有描述(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
为什么我的msg在 方法调用

因为您没有使用
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
的对象传递给该方法,然后更改其数据,但不能更改对此对象的引用。如果这是您的意图,那么您应该通过引用传递参数。

在您的方法中,您创建了一个全新的
Description
实例。对该实例的引用存储在局部变量
descrToChange

descrToChange
作为一个参数,是参考变量
msg.Description
的副本。方法中覆盖了
descrToChange
中的原始引用,而
msg.Description
中的引用保持不变

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

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

static void changeDescription(Description descrToChange)
{
    descrToChange.Key = 2;
    descrToChange.Value = "Foobar";
}
*解决方案#2:使用父项修改其子项*

另一种解决方案是使用
消息
作为参数:

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; }
}

你把参考资料写得太多了。您可以改为更改现有对象

static void changeDescription(Description descrToChange)
{
    descrToChange.Key = 2;
    descrToChange.Value = "Foobar";
}

快速补充Martin的答案,而不是在方法中调用
new
descrToChange.Key=2;descrToChange.Value=“Foobar”
将获得所需的结果,或使用
ref
关键字传递参数。更好的方法是传递
消息
(消息的
描述的分配
可以)或返回
描述
。意见:
ref
应该是一个不常用的关键字。@JTY:Thanx表示建议。@crashmstr:True。我将修改我的答案。嘿,如果我使用“ref”,我会得到以下错误:错误CS0206属性或索引器可能无法作为out或ref参数传递某些要研究的材料,我会认为这可能是现有问题的重复。您可以将
ref
关键字与
消息
类一起使用。您尝试过这个吗?它没有为我编译:'属性、索引器或动态成员访问可能不会作为out或ref参数传递',请downvoter解释一下有什么问题吗?先谢谢你。