2

看看下面的代码,告诉我为什么在调用函数 UpdateContext 后,变量 connection2 没有与变量 connection1 相同的哈希码。

当我将变量 connection2 设置为 connection1 时,两个变量都有一个指向相同内存地址的指针。但是在使用'new'指令修改指针的函数UpdateContext中通过ref传递变量connection1之后,connection1有一个新的指针地址,但connection2仍然是旧地址。

   class Program
   {
      static void Main(string[] args)
      {
         var connectionInitializer = new ConnectionInitializer();

         connectionInitializer.Initialize();

         Console.ReadLine();
      }
   }

   public class Connection
   {

   }

   public class ConnectionInitializer
   {
      public void Initialize()
      {
         var connection1 = new Connection();
         var connection2 = connection1;

         Console.WriteLine("Connection 1 (Before ref): " + connection1.GetHashCode());
         Console.WriteLine("Connection 2 (Before ref): " + connection2.GetHashCode());

         this.UpdateContext(ref connection1);

         Console.WriteLine("Connection 1 (After ref): " + connection1.GetHashCode());
         Console.WriteLine("Connection 2 (After ref): " + connection2.GetHashCode());
      }

      private void UpdateContext(ref Connection connection)
      {
         connection = new Connection();
      }
   }

感谢您的帮助。

4

5 回答 5

8

您似乎误解了ref要达到的目标。基本上,当您将变量作为ref参数传递时,它允许被调用者完全修改(原始)变量的值,就好像它是本地的一样。鉴于此,您为什么期望覆盖变量connection1的值也会更改分配给的值connection2

换句话说, usingref类似于以下代码:

var connection1 = new Connection();
var connection2 = connection1;
connection1 = new Connection()

显然在这种情况下,connection2应该是不变的。你的也是如此。

于 2012-06-07T00:03:53.793 回答
3

connection2仍然引用原始Connection对象。 connection1已被修改为引用一个新Connection对象。 connection1并且connection2不是字面上相同的参考。 connection2是这些引用的副本,connection1并且在一段时间内,这两个引用都引用了同一个对象。

除了它们所指的内容之外,这两个引用没有以任何有意义的方式链接,一个只是另一个的副本。更改原件不会影响副本。

于 2012-06-07T00:07:15.127 回答
1

虽然柯克沃尔的回答是正确的,但我认为当他说您误解了ref关键字时,他有点忽略了这一点。这种误解很常见,但更多的是对引用类型本身的性质的误解。

Kirk 的解释(“使用 ref 类似于此代码”)实际上反映了我记得的其他 SO 问题,例如“为什么下面的示例不打印Goodbye?”

string a = "Hello";
string b = a;
a = "Goodbye";
Console.WriteLine(b);

(抱歉,找不到实际问题的链接。)

如果您还记得引用类型变量存储对引用类型实例的引用,而值类型变量直接存储值类型的实例,那么跟踪就容易多了。

我发现这比通常的“引用类型通过引用传递;值类型通过值传递”要好得多。实际上,引用类型的变量(absent refor out)是通过value传递的,但 value 本身就是一个引用。这很令人困惑。更容易混淆:“引用类型变量持有对该类型实例的引用”。

当然,ref关键字使这有点复杂,因为 ref 参数包含对变量的引用。这意味着引用类型ref参数存储对该类型实例的引用的引用。同样,如果您考虑到引用类型变量包含引用的事实,您可以停止在 ref 参数处保存对变量的引用。这比“引用对...的引用”要容易得多。

于 2012-06-07T01:49:42.460 回答
0

当您初始化连接对象时,它会分配新的内存并因此分配新的哈希码

于 2012-06-07T00:04:49.927 回答
0

如果您说 C++,则 refs 和 outs 实际上只是指针,并且您正在传递所传递的标识符的地址。相比于:

void foo(int** p);

int main()
{
  int* one = new int(4);
  int* two = one;

  cout << "one|two before: " << *one << "|" << *two << endl;

  foo(&one);

  cout << "one|two after: " << *one << "|" << *two << endl;

  return 0;
}

void foo(int** p)
{
  *p = new int(5);
}

输出:

one|two before: 4|4
one|two after: 5|4

注意我本可以使用 c++ 引用传递,但在引擎盖下,这些也只是指针。

于 2012-06-07T00:10:51.953 回答