我知道传递给方法的引用类型可以修改。但我发现它只对参数的成员产生影响,而不是参数本身。这是一个测试:
这是一种参考类型:
class MyClass
{
public int PropInt { get; set; }
public string PropStr { get; set; }
public int FieldInt;
public string FiledStr;
}
此方法修改其成员:
void MyFun(MyClass myClass)
{
myClass.PropInt = 3;
myClass.FieldInt = 4;
myClass.PropStr = "c";
myClass.FiledStr = "d";
}
这会修改自身(null或new):
void MyFunNull(MyClass myClass)
{
myClass = new MyClass();
//myClass = null;
}
初始化:
MyClass myClass = new MyClass
{
PropInt = 1,
FieldInt = 2,
PropStr = "a",
FiledStr = "b"
};
测试:
---> output {1, 2, "a", "b"}
MyFun(myClass); ---> output {3, 4, "c", "d"}
MyFunNull(myClass); ---> output {3, 4, "c", "d"}
这是怎么回事?
在这种情况下,我必须使用out/ref
吗?
答案 0 :(得分:2)
这是因为参数中对象的引用将在您的方法中保持相同(除非您明确重新分配)。当您只更改其属性时,对原始实例没有任何影响。方法完成后,调用者仍然可以访问原始对象并查看更改的属性。参数中的原始实例与来自调用者的传入引用保持相同。
当您使用新的或重新分配更改参数时,除非您使用out
或ref
更改方法签名,否则调用者永远不会知道此更改。
如果您希望调用者知道在方法中重新分配或实例化的引用类型,则需要使用ref
keywoard(see msdn)
例如:
public void Foo(ref MyClass bar)
{
// Caller will get this new instance back
// after method completes.
bar = new MyClass()
}
更改参考: 以下示例将参数更改为某些预先存在的本地引用。
private MyClass myLocalBar
public void Foo(ref MyClass bar)
{
// Caller will get the modified reference
bar = this.myLocalBar;
}
您还可以使用out
(msdn)关键字执行类似的操作。但与ref
不同,out
将要求您为out
参数指定值。在对out
参数进行赋值之前尝试完成该方法将生成编译器错误。
public void Foo(out MyClass bar)
{
// We must assign a value to bar
bar = new MyClass()
}
以下将生成错误(取消评论最后一行以修复)
public void Foo(out MyClass bar)
{
// We must assign a value to bar
// Even null assignment is ok:
// bar = null;
}
out
参数始终保证调用者将返回新的/不同的引用。然而,ref
告诉调用者该方法可能修改或不修改原始引用。