I am still confused about passing by ref.
If I have a Cache object which I want to be accessed/available to a number of objects, and I inject it using constructor injection. I want it to affect the single cache object I have created. eg.
public class Cache {
public void Remove(string fileToRemove) {
...
}
}
public class ObjectLoader {
private Cache _Cache;
public ObjectLoader(Cache cache) {
}
public RemoveFromCacheFIleThatHasBeenDeletedOrSimilarOperation(string filename) {
_Cache.Remove(fileName);
}
}
Should I be using ref when I pass the Cache into the ObjectLoader constructor?
I think you're wondering how many copies of the
Cache
object will get created. You only want one copy to be shared by multiple client objects. Well, there's a very simple rule you can remember in C#, whenever you want to know how many separate copies of your object will be created.There are minor exceptions to this: you can call BCL methods that create objects, but the point is that it is explicit. You have to specifically ask for it to happen. The language will not automatically make copies of
class
objects.So in your example, you have a
class
calledCache
, and so you know for certain that you can pass around variables of typeCache
as much as you like, and no further copies ofCache
will be created. All the variables that have that object assigned to them will be "pointing" to the same original object. This is because aCache
variable doesn't store the object itself, but only the location of aCache
object in memory.Contrast this with what happens if you declare a
struct
type instead of aclass
. Now when you declare a variable of that type, the variable itself has to be large enough to store all the data declared in thestruct
. Every variable is a separate copy. Every parameter is a separate copy.You can override this by adding the
ref
keyword, but it's a pretty unusual keyword in most programs. Theout
keyword is more common, and is best thought of as a way to give a method more than one return value.What effect does
ref
have on a variable if it is ofclass
type? In your example:I could construct two object loaders like this:
How many objects did we just create? Simply count the
new
keywords. Now, suppose we added theref
keyword:Hidden inside that constructor, I've created another cache, and stored it in the parameter I was passed. Because it's a
ref
parameter, I've affected the caller's variable! So in the calling code:Now we have five uses of
new
: three in the above snippet, plus two calls to the modifiedObjectLoader
constructor. Each timeObjectLoader
's constructor is called, we pass itc
. We have to put theref
keyword, which is a very good thing because it lets the person reading the code know that something strange is going on. The variablec
points to a differentCache
afterObjectLoader
's constructor returns. Sob
'sObjectLoader
ends up storing a pointer to a differentCache
toa
!Needless to say, this would be quite a messy pattern for the code to have. It would be even worse if we didn't have to put the
ref
keyword at the calling site!Use the 'ref' keyword when the you need to modify what the reference is pointing to. When you pass a reference type into a method it is passed by value, but the value is a copy of that reference which is passed to the method. This means that you can change the general state (i.e., properties/fields) of the referred to object, but if you attempt to change what the reference points to you will only affect the copy.
For example, given this method...
We can pass in the argument and then see if it was affected:
Now, if we had defined the method using the 'ref' keyword...
The output would be "True", because the actual reference was passed to the method, not a copy. We changed what that reference points to within the function and we see the effects of those changes.
You are just creating a new pointer to the object on the heap when you omit the 'ref' keyword. If you change one pointer you will not change the other.
...
So, to answer your question; no, you do not need to use the 'ref' keyword to change the state of your single Cache object when it is passed to a method.
No you do not need to use the ref keyword in this situation.
Cache is a class, it is a reference type. When a reference is passed into a method, a copy of the reference (not the object itself) is placed into your parameter. Both references, inside and outside, of the method are pointing to the same object on the heap, and modification of the object's fields using one will be reflected in the other.
Adding ref to your method call passes in the original reference. This is useful in a situation where you would be reassigning (ie. by calling
new
) the location the reference points to from within a calling method.Objects are automatically passed by reference even when you declare them to be passed by value in function arguments, in the .NET framework.
This is because the object itself is a reference type, so you can modify the members of the object, even though you cannot replace the object itself.
See
http://msdn.microsoft.com/en-us/library/aa903253(VS.71).aspx