了解c#中的引用行为

时间:2015-10-06 18:13:19

标签: 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" };
    }

为什么我的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

3 个答案:

答案 0 :(得分:6)

在您的方法中,您创建了一个全新的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; }
}

答案 1 :(得分:3)

  

为什么我的消息后面有描述(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关键字的详细信息,请查看here

现在让我们了解一下:

descrToChange = new Description() { Key = 2, Value = "Foobar" };

在上面的代码行中,我们创建了一个新的Description对象,然后将其分配给descrToChange。但是,此变量descrToChange作为参数传递给方法,并且可以保存类型为Description的对象的引用。我们可以将类型为Description的对象传递给方法,然后更改它的数据,但我们无法更改对该对象的引用。如果这是你的意图,那么你应该通过引用传递参数。

答案 2 :(得分:0)

你覆盖了参考文献。您可以改为更改现有对象。

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