c#-4.0 - 如何传递字符串类型的属性

标签 c#-4.0 properties

我有以下代码(请注意,下面的代码不会更新属性)

private void queryResultsFilePath_Click(object sender, EventArgs e)
{
        Library.SProc.Browse browser = new Browse();
        browser.selectFile(QueryResultFilePath);
}

public class Browse
{

    public void selectFile(string propertyName)
    {
        ...
        propertyName = browserWindow.FileName;  
    }
}

现在我意识到我需要更改第二个方法,以便它返回一个字符串并手动将其分配给第一个示例中的属性。

我不确定的是,我认为当我分配一个引用类型作为方法的实际参数时,它在堆栈上的值的副本(即它在堆中的内存地址)被复制到新位置方法形参的堆栈,因此它们都指向堆上的同一内存地址。因此,当我更改形式参数的值时,它实际上会更改存储在堆上的值,从而更改实际参数值。

显然我错过了一些东西,因为我必须返回一个字符串并手动将其分配给属性。如果有人能指出我的误解,我会很感激。

谢谢。

最佳答案

我相信这里缺少的部分是:字符串是不可变的。

虽然您通过引用传递它,但一旦任何东西试图改变字符串,就会创建一个新字符串,而旧字符串保持不变。

我相信它是唯一具有强制不变性的引用类型。

来自MSDN :

Strings are immutable--the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this. For example, when you write this code, the compiler actually creates a new string object to hold the new sequence of characters, and that new object is assigned to b. The string "h" is then eligible for garbage collection.

进一步阅读:

http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/e755cbcd-4b09-4a61-b31f-e46e48d1b2eb

如果您希望该方法“更改”调用者的字符串,那么您可以使用 ref 关键字模拟:

public void SelectFile(ref string propertyName)
{
    propertyName = browserWindow.FileName;  
}

在此示例中,将在方法中分配参数 propertyName,因为使用了 ref,这也会更改调用者指向的字符串。请注意,此处仍然强制执行不变性。 propertyName 曾经指向字符串 A,但分配后现在指向字符串 B - 旧字符串 A 现在不再被引用,并将被垃圾回收(但重要的是仍然存在并且没有更改 - 不可变)。如果未使用 ref 关键字,调用者仍将指向 A,并且该方法将指向 B。但是,由于使用了 ref 关键字,现在 callers 变量指向字符串B。

这与以下示例效果相同:

static void Main(string[] args)
{
    MyClass classRef = new MyClass("A");
    PointToANewClass(ref classRef);
    // classRef now points to a brand new instance containing "B".
}

public static void PointToANewClass(ref MyClass classRef)
{
    classRef = new MyClass("B");
}

如果您在不使用 ref 关键字的情况下尝试上述操作,classRef 仍会指向包含“A”的对象,即使该类是通过引用传递。

不要混淆字符串语义和 ref 语义。并且不要混淆通过引用传递和赋值传递内容。从技术上讲,东西永远不会通过引用传递,指向堆上对象的指针是通过值传递 - 因此引用类型上的 ref 具有上面指定的行为。因此,不使用 ref 将不允许在调用者和方法之间“共享”新的赋值,该方法已收到自己的指向对象上的指针的副本。堆,取消引用指针具有通常的效果(查看相同的底层对象),但分配给指针不会影响调用者的指针副本。

关于c#-4.0 - 如何传递字符串类型的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10699103/

相关文章:

c# - MessageQueue.CanWrite 始终返回 true

c# - 有关 C# 4.0 中的代码契约的书籍

iphone - Objective-C 属性 - 使用 [self myProperty] 或 self.myProperty 是否比 myProperty 慢?

iphone - 将合成(保留)属性设置为 nil 时的 EXC_BAD_ACCESS

python - 为什么 python @property getter 方法每次调用都会运行两次,我可以停止它吗?

c# - 如果I <D>通过方差转换可转换为I <B>,则I <D>是否重新实现I <B>?

c# - 如何在屏幕上的某个位置模拟鼠标点击?

c#-4.0 - 如何将 IObservable/IObserver 与 ConcurrentQueue 或 ConcurrentStack 一起使用

ios - 在不调用 ViewDidLoad 的情况下从另一个类访问方法或属性?

swift - 计算属性内的 NSNumberFormatter