【问题标题】:C# Properties as Reference [closed]C# 属性作为参考 [关闭]
【发布时间】:2013-11-12 22:54:04
【问题描述】:

基本的我搞砸了 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 属性。这是字符串的特例吗?

【问题讨论】:

  • 在参数名称中使用下划线是不好(不寻常)的做法。
  • 这看起来很像这里的帖子:stackoverflow.com/questions/1402803/…,这可能有助于尝试通过引用传递属性。
  • 另外:“当我没有看到 ref 关键字时;这让我很担心” - 呃,为什么?我认为你的意思是相反的。
  • 我真的建议你多看看 C# @freewill。此外,尝试使用 refout、类和结构进行实验,直到您真正确定它们之间的区别。

标签: c# properties reference parameter-passing argument-passing


【解决方案1】:

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

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

你的第一种方法:

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 关键字,这将无法工作。

【讨论】:

  • 迈克尔解释得很好,+1。
  • 谢谢。这是解决我的问题并消除我的疑虑的确切描述。然而,其他朋友让我很难不使用 ref 关键字:)
  • 在需要的时候使用 ref 参数并没有错,但是你应该确保你真的需要它们。通常,希望拥有 ref 参数表明您的设计存在缺陷,可以通过更好的方式解决,
  • 感谢迈克尔,我已经深入研究了它。提供的一个更清晰、可读、更好的解决方案是返回一个“Result”类,而不是使用 ref 或 out 变量。我总是使用 bool 作为“返回”和 ref/out 用于方法中的状态代码和错误消息。我认为它来自旧习惯和旧式编程。现在结果类样式看起来真的更好。你一直很有帮助。非常感谢。
【解决方案2】:

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

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 对象的引用。

【讨论】:

  • 谢谢蒂姆。我会听从你关于 ref/out 和fundemantals 的建议。我有很多方法按顺序运行;在方法参数中都有“ref ErrorStatus err”引用;所有这些方法都将它们的错误状态添加到这个变量中(如记录器)。我会根据您的建议检查是否可以做得更好。
【解决方案3】:

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

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

当您调用 ChangeCountry(adr.Country) 时,您将地址对象的字符串属性 (Country) 传递给它,而不是传递给它一个 Address 对象。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 2010-09-16
    相关资源
    最近更新 更多