Tuesday, January 3, 2006

C# parameter passing rules

This page is a guide to how parameters should be passed in C#.

Rules for value types

valueTypeName variableNameThe normal way of passing.
ref variableNameCallee is invited to modify in-place.
out variableNameCallee must modify in-place.

Rules for reference types

ReferenceTypeName variableNameCallee may modify in place
ref ReferenceTypeName variableNameCallee is invited to modify in place or change what is referred to.
out ReferenceTypeName variableNameCallee must modify in place.

Examples

There follows a sketch of the declaration of a class with many methods, each handling different parameter types, passed in different ways. Look at each example below and refer back to the declaration of class G, to see the parameter declaration relevant to the call being made.


class G
{
 ...
 void useValueOf(string s);
 void modifyIfDesired(ref string s);
 void assignTo(out string s);

 void modifyIfDesired(object o);
 void modificationsWillBeIgnored(object copyOfO);
 void modifyIfDesiredOrPointToADifferentObject(ref object o);
 void assignTo(out object o);
}


Pass primitive type

g.useValueOf("hello");
string s = "world";
g.useValueOf(s);
// s must still be "world"

Pass primitive type when you want to allow it to be modified

string s = "bunnies";
g.modifyIfDesired(s);
// s might have changed

Pass primitive type, requiring that it is assigned to

string s;
g.modifyOrDie(s);
// Compiler ensures that callee assigns to s - gives error if not.

Pass reference type, callee may modify

Note that it is impolite for the callee to modify the argument. You should only modify an argument when it is passed as ‘ref’ or ‘out’. People don’t expect you to modify arguments which are passed ‘by value’, even though they really are references.
MyClass obj = new MyClass();
g.modifyIfDesired(obj);

Pass reference type

We really don’t want to see any changes the callee makes.
MyClass obj = new MyClass(); // implements ICloneable.
g.modificationsWillBeIgnored(obj.Clone());

Pass reference type

We are telling the callee that modifications are expected, though it doesn’t have to make any if it doesn’t want to. The callee may point our reference at a different object! Doing so is not a normal thing to do, however, and should be used only when absolutely necessary for some trickery - preferably with a mention in the method documentation.
MyClass obj = new MyClass();
g.modifyIfDesiredOrPointToADifferentObject(obj);

Pass reference type, callee must assign to it


MyClass obj;
g.assignTo(obj);
// obj has been assigned a value. Of course, it might have been assigned null!

No comments:

Post a Comment