2

我搞砸了 C# 属性和引用类型。

public Address adr { get; set; }

public class Address
{

    //Field
    public string AddressLine1;   

    //Property
    public string Country {get; set;}
}

public void ChangeCountry(string _Country)
{
    _Country = "US";
}

public void ChangeAddress(Address _adr)
{
    _adr.Country = "US";
}

private void button1_Click(object sender, EventArgs e)
{
    adr = new Address();
    ChangeCountry(adr.Country);

    MessageBox.Show(adr.Country);
    //(?)Country is reported empty string. Property did not updated outside.

    ChangeAddress(adr);

    MessageBox.Show(adr.Country);
    //OK. Country is reported 'US'


}

这是我的问题;

  1. 当我们将一个属性(简单的或复杂的)直接传递给一个尝试修改它的方法时,是否确保这个属性在任何地方都被修改了?我的意思是喜欢ref关键字?由于我不能将“ref”关键字与属性一起使用;我直接将属性传递给一个方法进行修改,我不确定它是否总是会在外部更新/修改。当我没有看到 ref 关键字时;这让我很担心:)

  2. 在上面的例子中;adr 类在没有 ref 关键字的情况下成功更新(ChangeAddress);但 ChangeCountry 方法无法更新字符串 Country 属性。这是字符串的特例吗?

4

3 回答 3

7

不,传递给方法的属性不会在该方法中修改,因为您不能通过引用传递它们。属性总是按值传递,因此您不能在传递它们两个的方法中更改它们的值。

但是,这实际上并不是您在这两种方法中所做的,这就是为什么一种有效而另一种无效的原因。

你的第一种方法:

public void ChangeCountry(string _Country)
{
    _Country = "US";
}

尝试更改没有ref关键字的参数的值,但失败(如您所述)。

你的第二种方法,

public void ChangeAddress(Address _adr)
{
    _adr.Country = "US";
}

不是试图改变其参数的值。Address您传递给该方法的对象Address对于整个方法保持相同的实例。但是,由于Address是引用类型,您可以更改其属性,并且这些更改将在方法返回后持续存在。它们也对引用同一实例的任何其他地方可见。

要查看差异,如果您尝试在第二种方法中执行此操作,它将失败,原因与第一种方法相同:

public void ChangeAddress(Address _adr)
{
    _adr = new Address();
    _adr.Country = "US";
}

在这里,您正在ref尝试将参数的值更改为类的新实例,而如果没有关键字,这将不起作用。

于 2013-11-12T23:03:32.120 回答
1

当我看到ref关键字时,它让我担心。在绝大多数情况下,有更好的解决方案。ref并且out应该谨慎使用。从我在您的示例中可以看到,我可以看到两种相当好的方法来解决您的问题:

string GetNewCountry() { return "US"; } // pass in existing Address if needed

adr.Country = GetNewCountry();

// or

public void ChangeAddress(Address adr)
{
    adr.Country = "US";
}

要回答您的第二个问题,strings 并不是特别特别,它们只是另一种不可变类型。如果您研究如何在 C# 中传递和修改引用,您看到的行为将非常清楚:在一种情况下,您正在修改可变Address对象,而在另一种情况下,您正在将局部变量替换为对一个不同的string对象。

于 2013-11-12T23:11:16.610 回答
0

这与通过引用传递的关系比您想象的要少。

您有ChangeCountry(Address a)接受类型对象的方法Address

当您Address调用.CountryChangeCountry(adr.Country)

要使您的代码修改Address对象,您需要调用ChangeCountry(adr).

于 2013-11-12T23:04:21.153 回答