Reputation: 1603
I know reference types passed to a method can be modified. But I found that it only takes effects on the parameter's members, not the param itself. Here is a test:
That is a reference type:
class MyClass
{
public int PropInt { get; set; }
public string PropStr { get; set; }
public int FieldInt;
public string FiledStr;
}
This method modifies its members:
void MyFun(MyClass myClass)
{
myClass.PropInt = 3;
myClass.FieldInt = 4;
myClass.PropStr = "c";
myClass.FiledStr = "d";
}
This modifies itself(null or new):
void MyFunNull(MyClass myClass)
{
myClass = new MyClass();
//myClass = null;
}
Initializing:
MyClass myClass = new MyClass
{
PropInt = 1,
FieldInt = 2,
PropStr = "a",
FiledStr = "b"
};
Test:
---> output {1, 2, "a", "b"}
MyFun(myClass); ---> output {3, 4, "c", "d"}
MyFunNull(myClass); ---> output {3, 4, "c", "d"}
How is that happening?
do I have to use out/ref
in this case?
Upvotes: 1
Views: 74
Reputation: 4893
This is because reference of the object in parameter will stay same within your method (unless you explicitly reassign). when you only change its properties, there is no impact on the original instance. When method completes, caller can still access the original object and see the changed properties. Original instance in parameter stayed same as the incoming reference from the caller.
When you change the parameter with a new or reassignment, caller is never aware of this change unless you change the method signature with out
or ref
.
If you want caller to be aware of a reference type being reassigned or instantiated in a method, you will need to modify it with ref
keywoard (see msdn)
For example:
public void Foo(ref MyClass bar)
{
// Caller will get this new instance back
// after method completes.
bar = new MyClass()
}
Changing the reference: following example changes the parameter to some preexisting local reference.
private MyClass myLocalBar
public void Foo(ref MyClass bar)
{
// Caller will get the modified reference
bar = this.myLocalBar;
}
You can also use out
(msdn) keyword do something similar. But unlike ref
, out
will require that you assign a value to the out
parameter. Attempting to complete the method before an assignment is done to out
parameter will generate compiler error.
public void Foo(out MyClass bar)
{
// We must assign a value to bar
bar = new MyClass()
}
Following will generate error (un-comment last line to fix)
public void Foo(out MyClass bar)
{
// We must assign a value to bar
// Even null assignment is ok:
// bar = null;
}
out
parameter always guarantees the caller that a new/different reference would be coming back. Whereas, ref
tells the caller that the method may or may not modify the original reference.
Upvotes: 2