3

可以链接哪些变量类型?我试图使用对象,但它没有做我想要的。

object a;
object b;
b = 5;
a = b;
b = 2;
label1.Text = Convert.ToString(a);

它写 5 但我希望它是 2。

4

3 回答 3

7

这是对引用及其工作方式以及变量是什么的简单误解。

object a; // a is a storage location
          // it holds references to instances of object

object b; // b is a storage location
          //it holds references to instances of object

b = 5; // "boxes" 5 into an instance of object
       // and assigns reference to that object to b

a = b; // assigns reference in storage location b to storage location a

b = 2; // "boxes" 2 into an instance of object
       // and assign reference to that object to b

像这样想。a并且b是一张纸,上面有住家的地址。当你说的时候,把它想象成在纸上b = 5写下一个家庭的地址。当你说的时候,把它想象成复制写在上面的地址。当你说的时候,把它想象成擦除写在上面的地址,并用回家的地址代替它。此操作不会更改写在纸上的值这就是这里发生的事情。5ba = bbab = 2b2a

现在,让我们看一个非常简单的方法来使您正在尝试做的工作。

class MyValue {
    public int Value { get; set; }
}

MyValue b = new MyValue { Value = 5 }; 
MyValue a = b;
b.Value = 2;

现在,如果你说

Console.WriteLine(a.Value);

会发生什么?让我们仔细推理。再次,回到上面写有地址的纸片的a类比b。我们已经说过MyValue b = new MyValue { Value = 5 }。可以把它想象成在纸上写下一个家庭的地址,前门上方b有一个标志。5将其a = b视为将写入的地址复制ba. 然后,考虑b.Value = 2更改前门上方标志上的值,在这种情况下,将 更改52。现在,如果有人问,那张纸上写着地址的房子门上方的价值是a多少?嗯,上面的地址和上面a的地址一样b. 我们只是将前门上方标志上的值从5更改为2。所以,我们期待看到2

试一试,试一试,您将看到2打印到控制台的值。

一遍又一遍地思考这个问题,直到你感觉到它在你的骨头深处。在你掌握这个基本概念之前,你会发现关于编程的推理非常具有挑战性。

于 2013-06-01T13:54:25.600 回答
5

杰森的回答很好;添加更多内容:

a = b当您说这意味着a并且b现在是同一个变量的别名时,您似乎期望这一点。这不是它的意思;a = b是指将存储位置的内容复制到存储b位置a,而不是重新标记存储位置a

然而,有一种方法可以使两个变量相互别名;事实上,在 C# 中有三种方法可以做到这一点(除了 Jason 建议的技术,这可能是最好的)。

第一种方式是使用refout参数:

class P
{
    static object b = 5;
    static void M(ref object a) 
    { 
        b = 2;
        Console.WriteLine(a);
    }
    static void Main()
    {
        M(ref b);
    }
}

如果你运行它,你会看到它做你想做的事。b开头为5,则ref意味着ab成为别名。什么时候b改成2,a也是因为它们是同一个变量有两个不同的名字。

但是,没有办法在单个方法中执行此操作。底层运行时确实支持这一点,我曾经制作了一个支持的 C# 版本:

object b = 5;
ref object a = ref b;
b = 2;
// now a is 2

但这从未成为交付给客户的语言版本。

使一个变量别名为另一个变量的第二种方法仅适用于高级程序员;您可以创建一个指针,在取消引用时为变量取别名:

int b = 5;
int* a = &b;
b = 2;
// Now *a is 2

请注意,指针类型只能为“非托管类型”的变量起别名,例如int,而不是托管类型,例如object.

我从事高级 C# 编程已有 10 年了,从来没有在生产代码中这样做过,所以如果我是你,我会避免使用它。

使一个变量别名为另一个变量的第三种方法仅适用于高级程序员;您可以使用TypedReferenceC# 的类型和一些未记录的特性来捕获对变量的引用,然后稍后取消引用到别名。我的建议是不要使用此功能。

于 2013-06-01T14:34:11.183 回答
0
using System;

class Program
{
    static void Main(string[] args)
    {
        ValueTypeWrapper<int> a;
        ValueTypeWrapper<int> b;

        // The following line creates a new instance
        // of ValueTypeWrapper<int> by the means of
        // implicit conversion (see last method defined
        // in the ValueTypeWrapper<T> class).
        b = 5;

        // Make the variable "a" point to the same
        // ValueTypeWrapper<int> instance we just created.
        a = b;

        // Now that both variables are pointing to
        // the same *instance*, change the value of
        // the Value property.
        b.Value = 2;

        // Convert.ToString(...) will call
        // ValueTypeWrapper<int>'s ToString()
        // method, which in turn produces the
        // string equivalent of the value inside
        // the Value property.
        // The Value property is equal to 2
        // on both "a" and "b" objects as they
        // point to the same instance.
        Console.WriteLine(Convert.ToString(a));
        Console.ReadLine();
    }
}

public class ValueTypeWrapper<T> where T : struct
{
    public T Value { get; set; }

    public override string ToString()
    {
        return this.Value.ToString();
    }

    public static implicit operator ValueTypeWrapper<T>(T value)
    {
        return new ValueTypeWrapper<T> { Value = value };
    }
}
于 2013-06-01T13:56:33.167 回答