10

我试过:

int i = 5;
object o1 = i; // boxing the i into object (so it should be a reference type)
object o2 = o1; // set object reference o2 to o1 (so o1 and o2 point to same place at the heap)

o2 = 8; // put 8 to at the place at the heap where o2 points

运行此代码后,o1 中的值仍为 5,但我预计为 8。

我错过了什么吗?

4

5 回答 5

20

这不是 C# 中变量的工作方式。它与装箱值类型无关。

考虑一下:

object o1 = new object();
object o2 = o1;

o2 = new object();

为什么你会期望o1o2包含对同一个对象的引用?设置时它们是相同的o2 = o1,但是一旦设置o2 = new object(),值(变量指向的内存位置)o2就会发生变化。

也许你想要做的事情可以这样做:

class Obj {
    public int Val;
}

void Main() {
    Obj o1 = new Obj();
    o1.Val = 5;
    Obj o2 = o1;
    o2.Val = 8;
}

最后Main, 的Val属性o1将包含8

于 2012-11-30T19:18:02.010 回答
5

要执行您想要执行的操作,该值必须是引用类型的属性:

public class IntWrapper
{
    public int Value { get; set; }
    public IntWrapper(int value) { Value = value; }
}

IntWrapper o1 = new IntWrapper(5);
IntWrapper o2 = o1;

o2.Value = 8; 
于 2012-11-30T19:22:59.140 回答
1

@Ken 给你完美的答案。这是如何使用struct(值类型)获得相同的行为。

注意:可变值类型有非常不直观的行为,不要在家里尝试这个:)。

要获得与值类型类似的行为,您需要实现一些接口并通过接口设置属性,因为取消装箱struct到它自己的类型将始终创建副本并且您将无法修改原始值。

void TortureMutableBoxedValueType()
{
  object o1 = new IntWrapper(5);
  object o2 = o1;
  Console.WriteLine(((IValue)o1).Value); // outputs original 5
  ((IValue)o2).Value = 8; 
  Console.WriteLine(((IValue)o1).Value); // outputs new 8
}

interface IValue 
{
  int Value {get;set;}
}

// Don't use mutable value types - this is just sample.
public struct IntWrapper : IValue 
{
  int v;
  public int Value { get { return v;} set {v = value;}}
  public IntWrapper(int value) { v = value; }
}
于 2012-11-30T22:01:12.237 回答
0

正如 Joel 指出的那样,即使 boxed 它仍然是一个值类型,因此它没有被引用,它被克隆了。这就是您看到此结果的原因 - o1 和 o2 指向不同的内存位置。

于 2012-11-30T19:22:49.847 回答
-2

也许不相关,但是如果您正在寻找一个整数作为引用类型(例如在某个方法中传递变量并对其进行一些操作并在退出方法后保留该值),那么您可以使用 ref 关键字。像这样:

int index = 0;

SomeMethod(ref index);

方法是这样的:

public void SomeMethod(ref int parameter)
{
   parameter++;
}
于 2018-09-17T18:35:24.310 回答