From my understanding passing a variable by reference means that the original variable that was passed into a function's parameters is changed. But also from my understanding a static variable means that the variable is changed when used as a parameter of a function. So don't both of these do the same thing?
From my understanding passing a variable by reference means that the original variable that was passed into a function's parameters is changed.
That location is passed, so yes; since the caller supplied the location, the caller can see the change.
But also from my understanding a static variable means that the variable is changed when used as a parameter of a function.
That's not what that means at all. A static field just exists as a field once per type (or per combination of generic type arguments). That's all it means. When you pass the value of a static field to a method, the value from the static field is read once and copied onto the stack, and that copy is passed to the method. The value of the static field will not be changed during the call.
Perhaps the confusion here is actually "reference types", not "pass by reference"; if a static field is actually a reference to an object, then changes to the object will be observed by all callers. But it isn't the field that changed: it is the object.
Related
For some reason, (I am new to C# and know java and c++) C# keeps copying objects when I want to pass by value. I have an arraylist of a Vector2 class, and whenever I want to increment a value, I have to do this:
Vector2 d = (Vector2) myObjects[i];
d.Y++;
myObjects [i] = d;
I want to be able to do this:
Vector2 d = (Vector2) myObjects[i];
d.Y++;
and be done. I searched the web and surprisingly no answers.
BTW the vector is a struct.
In C#, instances of classes are passed as references, whereas instances of structs are passed by copy (by default).
The answer was just where it was supposed to be: http://msdn.microsoft.com/en-us/library/vstudio/ms173109.aspx
A class is a reference type. When an object of the class is created, the variable to which the object is assigned holds only a reference to that memory. When the object reference is assigned to a new variable, the new variable refers to the original object. Changes made through one variable are reflected in the other variable because they both refer to the same data.
A struct is a value type. When a struct is created, the variable to which the struct is assigned holds the struct's actual data. When the struct is assigned to a new variable, it is copied. The new variable and the original variable therefore contain two separate copies of the same data. Changes made to one copy do not affect the other copy.
You are experiencing one of the effects of value-types. Because it copies itself by value, rather than by reference when assigned to new variables or passed as an argument.
You can pass a struct or other value type by ref, using the ref keyword in your method signature, unfortunately you can't use it for treating a variable in the same stack frame as a reference (i.e. you can't just say ref int test = yourArray[0], but must make something like:
public void SomeMethod(ref Vector2 input) {
// now you are modifying the original vector2
}
public void YourOriginalMethod()
{
SomeMethod(yourArray[20]);
}
In response to the comment below, from http://msdn.microsoft.com/en-us/library/14akc2c7.aspx:
Do not confuse the concept of passing by reference with the concept of
reference types. The two concepts are not the same. A method parameter
can be modified by ref regardless of whether it is a value type or a
reference type. There is no boxing of a value type when it is passed
by reference.
Let's say I have a method like this:
private void Method(string parameter)
{
// do some stuff with parameter
}
Is it acceptable to just use the parameter inside the method or is it better to declare a local variable as such:
private void Method(string parameter)
{
string localvariable = parameter;
// do some stuff with local variable
}
Does it matter performancewise? Is it more stable to declare a local variable?
Generally, there is no reason to assign a parameter's value to a local variable. In fact, a parameter is simply a special type of local variable that receives the value of the arguments passed to the method, http://en.wikipedia.org/wiki/Parameter_(computer_programming). You should use it throughout your method. Unless explicitly passed by reference, parameters are passed by value so you will not affect the value passed into the method call. When passing reference types, the "value" being passed is the reference (pointer) to the object so modifying properties or performing operations on the object that modify it will result in changes to it. For value types and strings which, being immutable, are treated specially, you should not have to worry about side effects to the variables passed to the method.
I learnt the reference type parameter passing is just a copy of the reference. If you set the passed in refernece parameter point to another object inside the called method, the orginal reference will not change.
I have a test method to test the reference type parameter passing. A refTest(SystemSwEvent systemSwEvent) method is called from that test method with a valid SystemSwEvent type object. Inside the refTest() method, the processEvScanDataAvailable(EvScanDataAvaialble systemSwEvent) method is called. Inside the processEvScanDataAvailable(EvScanDataAvaialble systemSwEvent) method, I set the passed in reference parameter to null. I expect the parameter in refTest() should not be changed. But that is not true. It will be changed to null momentarily. why?
The debugger recognizes the name in the current context and shows the value. It's just a coincidence that you pointed your cursor at a place that actually triggered the currently executing method (the current context).
Also note you can use the Call Stack tool to inspect the parameters of caller methods.
why?
I suspect this is a debugger issue, and not representative of what's actually occurring inside the CLR.
Try using different variable names for your arguments, and this behavior will go away.
Object references are by default (if you don't qualify them with ref or out) passed by value, so the method is receiving a copy of the object reference - setting that copy to null doesn't change the original object reference, so what you claim to see is impossible and most likely you are just misinterpreting what you see in the debugger.
The debugger is getting confused because your parameter and variable have the same name. If you change the name of your parameter, you will notice that that debugger no longer gives information about the variable being passed into the method, but only gives information on the variable inside the method.
Simply change the name of that parameter, and you will no longer have this issue.
Passing Value Type parameters to functions in c# is by value unless you use the ref or out keyword on the parameter. But does this also apply to Reference Types?
Specifically I have a function that takes an IList<Foo>. Will the list passed to my function be a copy of the list with copy of its contained objects? Or will modifications to the list also apply for the caller? If so - Is there a clever way I can go about passing a copy?
public void SomeFunction()
{
IList<Foo> list = new List<Foo>();
list.Add(new Foo());
DoSomethingWithCopyOfTheList(list);
..
}
public void DoSomethingWithCopyOfTheList(IList<Foo> list)
{
// Do something
}
All parameters are passed by value unless you explicitly use ref or out. However, when you pass an instance of a reference type, you pass the reference by value. I.e. the reference itself is copied, but since it is still pointing to the same instance, you can still modify the instance through this reference. I.e. the instance is not copied. The reference is.
If you want to make a copy of the list itself, List<T> has a handy constructor, that takes an IEnumerable<T>.
You're not alone; this confuses a lot of people.
Here's how I like to think of it.
A variable is a storage location.
A variable can store something of a particular type.
There are two kinds of types: value types and reference types.
The value of a variable of reference type is a reference to an object of that type.
The value of a variable of value type is an object of that type.
A formal parameter is a kind of variable.
There are three kinds of formal parameters: value parameters, ref parameters, and out parameters.
When you use a variable as an argument corresponding to a value parameter, the value of the variable is copied into the storage associated with the formal parameter. If the variable is of value type, then a copy of the value is made. If the variable is of reference type, then a copy of the reference is made, and the two variables now refer to the same object. Either way, a copy of the value of the variable is made.
When you use a variable as an argument corresponding to an out or ref parameter the parameter becomes an alias for the variable. When you say:
void M(ref int x) { ...}
...
int y = 123;
M(ref y);
what you are saying is "x and y now are the same variable". They both refer to the same storage location.
I find that much easier to comprehend than thinking about how the alias is actually implemented -- by passing the managed address of the variable to the formal parameter.
Is that clear?
The list is passed by reference, so if you modify the list in SomeFunction, you modify the list for the caller as well.
You can create a copy of a list by creating a new one:
var newList = new List<Foo>(oldList);
your list is passed by reference. If you want to pass a copy of the list you can do:
IList<Foo> clone = new List<Foo>(list);
if you add/remove elements in clone it won't modify list
but the modifications of the elements themselves will be taken into account in both lists.
When you pass reference type by value (without ref or out keywords) you may modify this reference type inside this method and all changes will reflect to callers code.
To solve your problem you may explicitly create a copy and pass this copy to your function, or you may use:
list.AsReadOnly();
When passing reference types, you pass the reference. This is an important concept.
If you pass a reference
byref, you pass the reference (pointer) directly.
byval, you pass a copy of the reference (pointer).
A reference is not the instance referenced. A reference is analagous to a pointer.
To pass a copy of the instance of a referencetype, you first must make a copy yourself and pass a reference to the copy. As such then you will not be modifying the original instance.
I think of DataGridView's as being memory hogs. Is it better to pass by value a datagridview or by reference? Should it even be passed at all?
Passing it by value or reference isn't going to matter from a memory stand point, because the DataGridView is a reference type, not a value type.
The type DataGridView is a reference type and hence it's not possible to pass the object by value. You can pass the reference to the object by value but that is a very small (typically pointer sized) value.
To add to Joseph's answer, All passing it by value does is create a new variable on the call stack in the called methods stack frame, and copy the address (in the Heap) of the DataGridView object into that variable for use by the called method. All this does is prevent the called method from assigning a new DataGridView object's address to the variable in the caller (calling method), and thus changing which dataGridView the caller will be pointing to.
You won't (need to) pass any Control very often
You cannot pass the object itself at all.
You can only pass the reference to an object, and doing so by value (the default) or by reference (ref parameter) has no impact on memory usage. It is a design decision but usually, certainly for Controls, you will pass the reference by value.