2013-06-01 35 views
3

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

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

它写出5,但我希望它是2.

+7

首先阅读MSDN上的[值类型和引用类型](http://msdn.microsoft.com/en-us/library/t63sy5hs.aspx)。 – Oded

+0

[拳击和拆箱](http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx)将是一个很好的第二页来通读。 – Oded

+0

in [值类型和引用类型](http://msdn.microsoft.com/en-us/library/t63sy5hs.aspx)它说“引用类型如Object”,so是object是引用类型还是不是? – halil12

回答

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 

想想这样。 ab是一些纸张,用于保存家庭地址。当你说b = 5时,可以认为它是在纸b上写下地址到家5。当你说a = b时,把它想象成复制写在ba的地址。当你说b = 2时,把它想象成擦除写在b上的地址并用地址代替它回到家2此操作不会更改写在纸张a上的值。这就是发生在这里。

现在,让我们看看一个非常简单的方法,使你想要做的工作。

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

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

现在,如果你说

Console.WriteLine(a.Value); 

会发生什么?让我们仔细推理。再次回到ab的比喻作为写有地址的纸张。我们已经说过MyValue b = new MyValue { Value = 5 }。想想这是写在纸上的b地址到一个家庭的标志说在前门上方5。把a = b认为是复制写在ba的地址。然后,考虑将b.Value = 2更改为前门上方标志的值,在此情况下,将5更改为2。现在,如果有人问,房子门上的价值是多少,写在纸上的地址是a?那么,a上的地址与b上的地址相同。我们只是将前门上方标志的值从5更改为2。所以,我们期望看到2

尝试一下,试试看,你会看到打印到控制台的值为2

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

+0

我可以链接两个变量而不使用数组吗? – halil12

+0

感谢您的回答:) – halil12

+0

@ halil12:如果您还有其他问题,请提出一个新问题。 –

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 }; 
    } 
} 
+0

谢谢您的回答 – halil12

+2

没问题。我喜欢它作为纯粹的学术演习。您应该考虑将贾森的帖子标记为答案,但是,他已经花了一些时间来解释价值和参考类型之间的差异 - 您应该仔细阅读并尝试吸收。 –

+0

如果你只是稍微描述一下这个概念,那就太好了。 –

5

杰森的回答很好;更添加到它:

你似乎期望,当你说a = b,这意味着ab和现在相同的变量的别名。这不是什么意思; a = b表示将存储位置b内容复制到存储位置a而不是重新标记存储位置a

There is然而一种使两个变量相互混淆的方法;实际上有三种方法可以在C#中完成这三种方式(除了杰森建议的技术之外,这可能是最好的)。

第一种方式是使用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#十年,并且从来没有在生产代码中这样做过,所以如果我是你,我会避免它。

使另一个变量别名的第三种方法是仅适用于高级程序员;您可以使用TypedReference类型和C#的一些未公开的功能来捕获对变量的引用,然后再取消引用别名。我的建议是不使用此功能。

+0

我想问一个问题。我可以发送一个数组的元素作为参考? – halil12

+2

@ halil12:是; *任何*变量都可以通过'ref'传递。数组元素是一个变量。你不能通过ref的一件事是*属性*;具有getter和setter的属性实际上并不是一个变量。 –