可以链接哪些变量类型?我试图使用对象,但它没有做我想要的。
object a;
object b;
b = 5;
a = b;
b = 2;
label1.Text = Convert.ToString(a);
它写 5 但我希望它是 2。
这是对引用及其工作方式以及变量是什么的简单误解。
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
写下一个家庭的地址。当你说的时候,把它想象成复制写在上面的地址。当你说的时候,把它想象成擦除写在上面的地址,并用回家的地址代替它。此操作不会更改写在纸上的值。这就是这里发生的事情。5
b
a = b
b
a
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);
会发生什么?让我们仔细推理。再次,回到上面写有地址的纸片的a
类比b
。我们已经说过MyValue b = new MyValue { Value = 5 }
。可以把它想象成在纸上写下一个家庭的地址,前门上方b
有一个标志。5
将其a = b
视为将写入的地址复制b
到a
. 然后,考虑b.Value = 2
更改前门上方标志上的值,在这种情况下,将 更改5
为2
。现在,如果有人问,那张纸上写着地址的房子门上方的价值是a
多少?嗯,上面的地址和上面a
的地址一样b
. 我们只是将前门上方标志上的值从5
更改为2
。所以,我们期待看到2
。
试一试,试一试,您将看到2
打印到控制台的值。
一遍又一遍地思考这个问题,直到你感觉到它在你的骨头深处。在你掌握这个基本概念之前,你会发现关于编程的推理非常具有挑战性。
杰森的回答很好;添加更多内容:
a = b
当您说这意味着a
并且b
现在是同一个变量的别名时,您似乎期望这一点。这不是它的意思;a = b
是指将存储位置的内容复制到存储b
位置a
,而不是重新标记存储位置a
。
然而,有一种方法可以使两个变量相互别名;事实上,在 C# 中有三种方法可以做到这一点(除了 Jason 建议的技术,这可能是最好的)。
第一种方式是使用ref
和out
参数:
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
意味着a
和b
成为别名。什么时候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 年了,从来没有在生产代码中这样做过,所以如果我是你,我会避免使用它。
使一个变量别名为另一个变量的第三种方法仅适用于高级程序员;您可以使用TypedReference
C# 的类型和一些未记录的特性来捕获对变量的引用,然后稍后取消引用到别名。我的建议是不要使用此功能。
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 };
}
}