结构也是可以按引用传递的, 如果 A 是结构类型, 就添加 ref 修饰符,修改 ChangeA 方法的声明,通过引用传递变量:
public static void ChangeA ( ref A a )
{
a.X = 2;
}
public struct A
{
public int X { get; set; }
}
static void Main ()
{
A a1 = new A () { X = 1 };
ChangeA ( ref a1 );
Console.WriteLine ( string.Format( "a1.X: {0}", a1.X ) );
}
现在,与类类型一样, 结构也按引用传递,所以结果是 2。
类类型如何使用 ref 修饰符呢? 下面修改 ChangeA 方法的实现:
public static void ChangeA ( A a )
{
a.X = 2;
a = new A { X = 3 }; // new
}
public struct A
{
public int X { get; set; }
}
static void Main ()
{
A a1 = new A () { X = 1 };
ChangeA ( a1 );
Console.WriteLine ( string.Format( "a1.X: {0}", a1.X ) );
}
使用 A 类型的类, 可以预期有什么结果 ? 当然, Main() 方法的结果不是 1,也不是 3, 而是 2, 为什么呢? 因为按引用传递是通过类类型实现的。 a.X 设置为 2, 就改变了原始对象的 a1。 然后, 下一行 a = new A { X = 3 } 现在在堆上创建一个新的对象, 和一个新对象的引用。 Main()方法中使用的变量 a1 仍然引用值为 2 的旧对象。 ChangeA 方法结束后, 没有引用堆上的新对象, 会被回收, 所以这里的结果是 2.
这里要记录一个点: 就是说传递引用时, 只允许改变引用下的值而不是引用本身, 上面的例子就犯了这个错误, 它试图创建一个新的引用来改变它。
把 A 作为类类型, 使用 ref 修饰符, 传递对引用的引用 (C++术语中, 叫做指向指针的指针), 它允许分配一个新对象,如下示例它的结果就是 3:
public static void ChangeA ( ref A a)
{
a.X = 2;
a = new A () { X = 3 };
}
注意: 一定要理解, C# 对传递给对方的参数初始化要求。 任何变量传递给方法之前, 必须初始化, 无论是按值还是按引用传递。