【问题标题】:I declared a variable for a class, and passed it into a method to instantiate it, but the original variable remains uninstantiated我为一个类声明了一个变量,并将其传递给一个方法来实例化它,但原始变量仍未实例化
【发布时间】:2015-12-25 20:18:07
【问题描述】:

我知道类总是通过引用传递不同于通过值传递的结构。

如果你看一下下面的代码,你会发现我调用了一个没有ref 关键字的函数(假设不​​需要它,因为Path 是一个类,因此它应该总是由 ref 自动调用不需要ref 关键字)。

public MainWindow()
{
    InitializeComponent();      
    Func(myPath);

    if (myPath == null)
       MessageBox.Show("AAAARGH");
}

Path myPath;

private void Func(Path p)
{
    if (p == null)
        p = new Path();
}

所以在函数调用之后,我希望myPath 不再是null,因为它已在Func() 中初始化,但事实并非如此。

我正在研究全球价值。这会改变什么吗?

【问题讨论】:

  • 通过引用传递,如果没有 ref 关键字,您仍然无法更改该引用指向的位置。您可以修改该对象的属性,但不能创建新对象并将其保留回调用者。
  • 这真是糟糕的设计。为什么不直接使用myPath?此外,无论您在做什么,它都不属于后面的代码。创建合适的 ViewModel。
  • 我正在制作多路径画布。相同的功能既可以在新路径上操作,也可以在用户通过鼠标选择的路径上操作。这就是为什么我有一个代表 mouseSelectedPath 的 myPath。那就是说你是对的,我将重新阐述我的代码,尽量不使用全局路径。还有一件事:为什么不使用代码隐藏?这是一个相当复杂的程序,所以我无法将所有内容都放在 xaml 文件中。
  • 错了。如果参数没有refout,则一切(无论类型如何)都是按值传递。如果参数具有refout,则所有内容(无论类型如何)都是通过引用传递的。

标签: c# function pass-by-reference pass-by-value


【解决方案1】:

通过引用传递值与使用ref 关键字非常不同。将其翻译成 C 或 C++ 术语:

  • 传递一个对象就像传递一个指针
  • 传递一个对象 ref 就像将指针传递给指针。

如果要更改函数内部变量的值,则需要使用refout

【讨论】:

  • 通过引用传递完全是使用ref关键字。
【解决方案2】:

你必须用'out'标记参数。

有关“out”的更多信息,请查看:

https://msdn.microsoft.com/en-us/library/t3c3bfhx.aspx

【讨论】:

  • 在所描述的场景中,'out' 的使用优于 'ref',因为它可以更清晰地传达方法调用的意图。再一次,最准确的答案没有得到复选标记。
【解决方案3】:

当您最初调用Func()myPathp 时,引用Path 的同一个实例。但是,myPathp 仍然是两个独立的引用,它们恰好指向同一个实例。

也就是说,直到下面的代码运行:

p = new Path();

之后,p 引用了一个与原始实例不同的 Path 的新实例。更改p 引用的实例中的属性将不会反映在myPath 引用的实例中。

换句话说:

private void Func(Path p)  // p is a separate reference, referencing same Path as myPath
{
    if (p == null)         // p still references same Path as myPath
        p = new Path();    // now p references a new instance of Path, separate from myPath
}

您可以使用ref(或out)关键字,以便myPath 标识的引用本身是“按引用”传递的,其效果是myPathp 是一个单一的参考。

然后,当您在方法中创建 Path 的新实例时,myPathp 仍然是一个引用,都指向新实例。 (您的原始实例仍在内存中某处,但不再引用它。)

Path myPath = null;

private void Func(ref Path p)  // p is same reference as myPath
{
    if (p == null)
        p = new Path();        // p and myPath are still same reference,
                               //   now referencing a new instance of Path
}

或者:

Path myPath;

private void Func(out Path p)  // p is same reference as myPath
{
    if (p == null)     
        p = new Path();        // p and myPath are still same reference,
                               //   now referencing a new instance of Path
}

【讨论】:

  • 错了。 “类的实例”不是 C# 中的值,不能“通过”。当你创建一个实例时,你会得到一个reference(一个引用类型的值),你只能通过这些references来操作实例。这些引用可以按值(不带refout)或通过引用(带refout)传递。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-22
  • 2015-03-17
  • 2014-01-06
  • 2015-06-09
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多