If the object being referenced as a parameter is being modified in a function, does it matter if you use ref or not? Is there a difference between the following two functions?
void DisposeObject(ClassThing c)
{
c.Dispose();
}
void DisposeObject(ref ClassThing c)
{
c.Dispose();
}
It doesn't matter. What matters is if you're assigning something to c (and want it reflected outside the method):
c = new ClassThing();
In that case you'd use ref.
It doesnt depend in your case.
BUT:
if you pass a reference object with the ref keyword you have inside of the method the possibility to change the reference to point to another Object of this type (so it will be visible outside of the method)
According to the MSDN guide to passing reference-type parameters:
When you pass a reference-type parameter by value, it is possible to change the data pointed to by the reference, such as the value of a class member. However, you cannot change the value of the reference itself; that is, you cannot use the same reference to allocate memory for a new class and have it persist outside the block. To do that, pass the parameter using the ref or out keyword.
So you can alter the original object, but you cannot change the original object to reference a different location in memory. Example:
static void Main()
{
int[] integerArray = new int[8];
foo(integerArray);
}
private void foo(int[] myArray)
{
myArray[0] = 5; //this changes integerArray
myArray = new int[4]; //this does not change integerArray,
// ... but it would if you used ref or out
}
So the difference does matter, although I don't know specifically about the behavior of Dispose().
Related
I have a programming competition tomorrow and I have a quick question:
In Java, if you would pass an object in a parameter for a method, you actually got not a copy of the object, but the actual object.
Is it the same as C#?
public static void PunchyManager(string[] inputArray, ref int a, ref int b)
{
string[] tempStrArray = inputArray;
}
If I do that will I basically make a pointer to inputArray, instead of having a copy?
Just a quick question, thanks!
In regard to your basic question in relation to Java Yes.
More generally Yes and no. Reference types (classes) are passed by reference which is like a single pointer. For something that can truly modify references outside the caller you should use the ref keyword even on reference types. This is similiar to a double pointer (assuming we are referring to pointers as they work in C for our pointer analogies).
class RefRefExample
{
static void Method(ref string s)
{
s = "changed";
}
static void Main()
{
string str = "original";
Method(ref str);
// str is now "changed"
}
}
In the above example if we passed str without using the ref keyword we would reassign the local reference of s instead of the original reference of str. By passing our reference by reference we can modify the original reference outside of the function as well. References themselves are still copied by value (but the copied reference still points to the same value) without the ref keyword.
http://msdn.microsoft.com/en-us/library/14akc2c7(v=vs.80).aspx
For practical usage in the scenario you are describing the modern C# idiom usually uses lists and they will likely be much faster to use as far as programming in your competition:
public static void PunchyManager(List<string> inputList, ref int a, ref int b)
{
var tempList = new List<string>();
foreach (var item in inputList)
tempList.Add(item);
}
Working on the original input list would modify objects through the reference so you would be affecting the original values outside of the method whereas the templList is a copy - Lists are very convenient.
Furthermore you can convert them back to Arrays using .ToArray()
*edit Oh, you wish to know if it is the same in c# as java, your wording was a bit off.
Correct, if you do
public static void main(String[] args)
{
int myArray[] = new int[1];
test(myArray);
System.out.println(myArray[0]);
}
public void test(int[] array)
{
array[0] = 1;
}
You will get an output of 1
In CLR there are two kinds of objects:
Reference types (also known as just "objects")
Value types (also known as "structures" or "structs", even they are technically objects too).
The difference between them is that "objects" are located on heap, when "structs" are located on stack.
Types like Int32, Int64, Float, Double, etc are value types (structs). You can also define your own structure:
public struct MyStruct { ... }
Therefore, when you pass a "struct" around it is passed by copying the value.
Example:
int x = 5; //creates a value type on stack
int y = x; //makes a copy so now we have two objects on stack, not just one
"Objects" are passed by reference.
object x = new Object(); //create an object, x holds a reference to this object
object y = x; // y now holds a reference to the same object x has a reference to.
When you pass reference types around you generally don't need to use a ref keyword. However, if you want to pass a reference to a value type instance you may want to use this keyword.
Yes, class instances are passed as references in C#. If you want to pass value type (like Int32) as reference you need to use ref keyword.
Thing is, If you pass the parameter with keyword ref, modification of the variable inside the method will be reflected to caller as well. This is applicable to even struct(exmple int). But for struct or class, if you pass the parameter with out ref/out, this will be assumed as pass by value, which means, modification inside the method cannot be reflected to caller for structs. For classes, modification will be reflected to caller still without passing with out ref. BUT, StringBuilder sb = new StringBuilder() statement ask the sb to point to this one (an newly created new StringBuilder()). So reference knot will be moved from one which was pointed in the caller to new StringBuilder() in the callee. This has to be remembered always.
Pass by value with ref:
static void Main(string[] args)
{
StringBuilder y = new StringBuilder();
y.Append("hello");
Foo(ref y);
Console.WriteLine(y);
}
private static void Foo(ref StringBuilder y)
{
StringBuilder sb = y;
sb.Append("99");
}
o/p : hello99
Pass by value without ref:
static void Main(string[] args)
{
StringBuilder y = new StringBuilder();
y.Append("hello");
Foo(y);
Console.WriteLine(y);
}
private static void Foo(StringBuilder y)
{
StringBuilder sb = new StringBuilder
sb.Append("99");
}
o/p : hello
To assign something different to your array you'd want to have the parameter use the 'ref' keyword.
http://msdn.microsoft.com/en-us/library/szasx730(v=vs.71).aspx
I am reading Jeffrey Richters CLR via C#, and in it he says with ref parameters the reference itself is passed by value. This makes sense to me and seems analagous to pointers.
i.e. in C if I pass a pointer into a function and then assign the pointer via malloc it changes the pointer to point to the new memory location, however I know since the pointer itself is a copy it doesn't reassign the original pointer that was passed into the function. In order to accomplish change to the pointer outside the function I have to use a double pointer.
However, in C#:
void Swap(ref Object a, ref Object b)
{
Object t = b;
b = a;
a =t ;
}
works. This indicates to me that references aren't by value.
In analogy to the malloc above, I am assuming I could pass an object by reference and assign it a new object and the reassignment would persist outside the function.
Can someone clearup my confusion?
You have it slightly off. With reference types, the references are passed by value. Passing a ref parameter is different. In
private void Frob(Foo foo) // Foo is a class
{
}
A copy of the reference to the object of type Foo at the call site is passed into the method Frob. This copy of the reference is passed by value. This reference and the reference at the call site point to the same object in memory and will continue doing so until one of them is pointed at some other object in memory. For example, if inside this method, we write
foo = someOtherFoo;
Then the parameter is no longer referring to the same object as the object at the call site. The call site reference is unchanged.
Now consider if we introduce the ref keyword.
private void Frob(ref Foo foo)
{
foo = someOtherFoo;
}
In this situation, foo is an alias of the variable at the call site. These variables are not merely pointing at the same object in memory, it's as if they are the same variable! As a result, pointing foo to someOtherFoo is not only going to change foo inside this method, this change will also be reflected at the call site.
Without the ref keyword, an object's reference is passed by value.
With the ref keyword, a reference to an object's reference is passed by value.
[it's just that the compiler is hiding the fact that making the assignment to a parameter passed by explicit ref is changing the pointer]
When called this passes the original pointer value (the reference)
void Swap(ref Object a, ref Object b)
{
Object t = b;
b = a;
a = t;
}
This passes a copy of the original pointer:
void Swap(Object a, Object b)
{
Object t = b;
b = a;
a = t;
}
Both will point to the same object but changing the second won't be reflected in a greater scope that this method...
I do not exactly get the question though...
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
When to pass ref keyword in
Hi All,
I am just surprised that why we have ref in C# while by default everything which is a reference type in C# is passed as a reference.
In simpler words, can anyone explain me the difference between these two method calls:
public void Test(SomeClass someClass)
{
// some code here
}
and
public void Test(ref SomeClass someClass)
{
// some code here
}
In my thinking they both have reference to same memory location.
So why do we need ref keyword at all ?
The ref keyword passes in a reference to whatever location is storing the reference. This allows you to manipulate this variable from the called function. This is particularly useful for value types, but also has uses when used with reference types. (Dictionary.TryGetValue() being a good example. The out parameter is required to return the value stored in the dictionary. out is equivalent to ref except that it will undergo a different set of compile-time checks.)
For example:
public void Test(ref SomeClass obj)
{
obj = null;
}
public void Test2(SomeClass obj)
{
obj = null;
}
public void Foo()
{
SomeClass obj = new SomeClass();
Test(ref obj);
// obj is null here!
obj = new SomeClass();
Test2(obj);
// obj is not null here.
}
I am just surprised that why we have ref in C# while by default everything is which is a reference type in C# is passed as a reference.
Because some things in C# are value types, and sometimes we want to pass those. We have the ref keyword so that those things can be passed by reference also.
It's analogous to the difference between a SomeClass * and a SomeClass ** in C++.
With a SomeClass * (or without ref), we can modify the object pointed to, but we can't redirect it to an entirely new object.
With a SomeClass ** (or with ref), we can change the argument in the calling code in order to point it to an object of our choosing.
When you pass an object you pass it by reference. This means that anything you do to that object will be reflected in the object after the method returns. When you pass the reference by reference i.e. void Foo(ref object obj) you are passing the address of that object. You can then re-assign the address to a different object and that will be the state of things when the method returns
foo (object o)
{
...
}
var v = new object();
foo(v);
v will still reference the same object that was instantiated prior to the call to foo
void bar(ref object o)
{
o = null;
}
var v = new object();
foo(ref v);
// v is now null
Suppose method Foo accepts a Bar by value. If I have a Bar called "Boz", the statement:
Foo(Boz);
may take the object pointed to by Boz and change that object's characteristics, but it cannot change which object Boz points to. By contrast, if Boz were passed by reference, the same statement could cause Boz to point to a different object entirely.
As an example of usage, consider a routine that accepts an array as a parameter. If an array is passed by value, the recipient can change the value of any of the items in the array, but the recipient cannot change the size. The only way to change the size of an array is to create a new array, copy the old items into it, and from thence forth use the new array instead of the old one. When an array passed by value, there is no way for the recipient to tell the caller that it should stop using the old array and use the new one instead. With an array passed by reference that is not a problem.
I understand (or at least I believe I do) what it means to pass an instance of a class to a method by ref versus not passing by ref. When or under what circumstances should one pass a class instance by ref? Is there a best practice when it comes to using the ref keyword for class instances?
The clearest explanation I've ever run across for output and ref parameters is ... Jon Skeet's.
Parameter Passing in C#
He doesn't go into "best practices", but if you understand the examples he's given, you'll know when you need to use them.
When you may replace the original object, you should send him as ref. If it's just for output and can be uninitialized before calling the function, you'll use out.
Put succinctly, you would pass a value as a ref parameter if you want the function you're calling to be able to alter the value of that variable.
This is not the same as passing a reference type as a parameter to a function. In those cases, you're still passing by value, but the value is a reference. In the case of passing by ref, then an actual reference to the variable is sent; essentially, you and the function you're calling "share" the same variable.
Consider the following:
public void Foo(ref int bar)
{
bar = 5;
}
...
int baz = 2;
Foo(ref baz);
In this case, the baz variable has a value of 5, since it was passed by reference. The semantics are entirely clear for value types, but not as clear for reference types.
public class MyClass
{
public int PropName { get; set; }
}
public void Foo(MyClass bar)
{
bar.PropName = 5;
}
...
MyClass baz = new MyClass();
baz.PropName = 2;
Foo(baz);
As expected, baz.PropName will be 5, since MyClass is a reference type. But let's do this:
public void Foo(MyClass bar)
{
bar = new MyClass();
bar.PropName = 5;
}
With the same calling code, baz.PropName will remain 2. This is because even though MyClass is a reference type, Foo has its own variable for bar; bar and baz just start out with the same value, but once Foo assigns a new value, they are just two different variables. If, however, we do this:
public void Foo(ref MyClass bar)
{
bar = new MyClass();
bar.PropName = 5;
}
...
MyClass baz = new MyClass();
baz.PropName = 2;
Foo(ref baz);
We'll end up with PropName being 5, since we passed baz by reference, making the two functions "share" the same variable.
The ref keyword allows you to pass an argument by reference. For reference types this means that the actual reference to an object is passed (rather than a copy of that reference). For value types this means that a reference to the variable holding the value of that type is passed.
This is used for methods that need to return more than one result but don't return a complex type to encapsulate those results. It allows you to pass a reference to a object into the method so that the method can modify that object.
The important thing to remember is that reference types are not normally passed by reference, a copy of a reference is passed. This means that you are not working with the actual reference that was passed to you. When you use ref on a class instance you are passing the actual reference itself so all modifications to it (like setting it to null for example) will be applied to the original reference.
When passing reference types (non-value-types) to a method, only the reference is passed in both cases. But when you use the ref keyword, the method being called can change the reference.
For example:
public void MyMethod(ref MyClass obj)
{
obj = new MyClass();
}
elsewhere:
MyClass x = y; // y is an instance of MyClass
// x points to y
MyMethod(ref x);
// x points to a new instance of MyClass
when calling MyMethod(ref x), x will point to the newly created object after the method call. x no longer points to the original object.
Most use cases for passing a reference variable by reference involve initialization and out is more appropriate than ref. And they compile to the same thing (the compiler enforces different constraints - that ref variables be initialized before being passed in and that out variables are initialized in the method). So the only case I can think of where this would be useful is where you need to do some checking of an instantiated ref variable and may need to reinitialize under certain circumstances.
This might also be necessary to modify an immutable class (like string) as pointed out by Asaf R.
I found that it is easy to run into trouble using the ref keyword.
The following method will modify f even without the ref keyword in the method signature because f is a reference type:
public void TrySet(Foo f,string s)
{
f.Bar = s;
}
In this second case however, the original Foo is affected only by the first line of code, the rest of the method somehow creates and affects only a new local variable.
public void TryNew(Foo f, string s)
{
f.Bar = ""; //original f is modified
f = new Foo(); //new f is created
f.Bar = s; //new f is modified, no effect on original f
}
It would be good if the compiler gave you a warning in that case. Basically what you are doing is replacing the reference you received with another one referencing a different memory area.
It you actually want to replace the object with a new instance, use the ref keyword:
public void TryNew(ref Foo f, string s)...
But are you not shooting yourself in the foot? If the caller is not aware that a new object is created, the following code will probably not work as intended:
Foo f = SomeClass.AFoo;
TryNew(ref f, "some string"); //this will clear SomeClass.AFoo.Bar and then create a new distinct object
And if you try to "fix" the problem by adding the line:
SomeClass.AFoo = f;
If the code holds a references to SomeClass.AFoo somewhere else, that reference will become invalid...
As a general rule, you probably should avoid using the new keyword to alter an object which you read from another class or received as a parameter in a method.
Regarding the use of the ref keyword with reference types, I can suggest this approach:
1) Don't use it if simply setting the values of the reference type but be explicit in your function or parameter names and in the comments:
public void SetFoo(Foo fooToSet, string s)
{
fooToSet.Bar = s;
}
2) When there is a legitimate reason to replace the input parameter with a new, different instance, use a function with a return value instead:
public Foo TryNew(string s)
{
Foo f = new Foo();
f.Bar = s;
return f;
}
But using this function may still have unwanted consequences with the SomeClass.AFoo scenario:
SomeClass.AFoo = TryNew("some string");//stores a different object in SomeClass.AFoo
3) In some cases such as the string swapping example here it is handy to use ref params, but just as in case 2 make sure that swapping the object addresses does not affect the rest of your code.
Because it manages memory allocation for you, C# makes it all too easy to forget everything about memory management but it really helps to understand how pointers and references work. Otherwise you may introduce subtle bugs that are difficult to find.
Finally, this is typically the case where one would want to use a memcpy like function but there is no such thing in C# that I know of.
I want to give a certain linked list to a class I am making. I want the class to write into that list (eg by .addLast()).
Should I use the ref keyword for that?
I am somewhat puzzled on where to use the ref and out keywords in C#, as all classes are allocated dynamically on the heap and we actually use pointers for most operations.
Of course, out and ref keywords make sense for primitives and structs.
Also, if I don't send the list directly, but send a class containing the list? (it's internal and needed), do I still need to use ref? or if I pass it between functions, ex:
void A(ref LinkedList<int> list){
B(list);
}
void B(ref LinkedList<int> list){
_myList = list;
}
This is a common misconception of the use of ref keyword in C#. Its purpose is to pass either a value or a reference type by reference, and you only need it in specific circumstances where you need a direct reference to the actual argument, rather than a copy of the argument (be it a value or reference itself). It is imperative not to confuse reference types with passing by reference in any case.
Jon Skeet has written an excellent article about parameter passing in C#, which compares and contrasts value types, reference types, passing by value, passing by reference (ref), and output parameters (out). I recommend you take some time to read through this in full and your understanding should become much clearer.
To quote the most important parts from that page:
Value parameters:
By default, parameters are value
parameters. This means that a new
storage location is created for the
variable in the function member
declaration, and it starts off with
the value that you specify in the
function member invocation. If you
change that value, that doesn't alter
any variables involved in the
invocation
Reference parameters:
Reference parameters don't pass the
values of the variables used in the
function member invocation - they use
the variables themselves. Rather than
creating a new storage location for
the variable in the function member
declaration, the same storage location
is used, so the value of the variable
in the function member and the value
of the reference parameter will always
be the same. Reference parameters need
the ref modifier as part of both the
declaration and the invocation - that
means it's always clear when you're
passing something by reference. Let's
look at our previous examples, just
changing the parameter to be a
reference parameter:
To conclude: having read my reply and Jon Skeet's article, I hope that you will then see that there is no need whatsoever for using the ref keyword in the context of your question.
For what you're doing you don't need to use ref. If you did pass the list using ref, you would be allowing the caller to change which list you're referencing, rather than just changing the contents of the list.
The only time you need to use ref with a reference type is if you're going to be creating a new object inside a function.
Example #1: ref keyword not necessary.
// ...
List myList = new List();
PopulateList(myList);
// ...
void PopulateList(List AList)
{
AList.Add("Hello");
AList.Add("World");
}
Example #2: ref keyword necessary.
// ...
List myList;
PopulateList(ref myList);
// ...
void PopulateList(ref List AList)
{
AList = new List();
AList.Add("Hello");
AList.Add("World");
}
I know this is an old question, but none of the answers give a good direct reason why in my opinion.
You don't need to use ref in this instance, and here's why. Consider this function:
void Foo(MyClass a1, ref MyClass a2, out MyClass b1, int c1, MyStruct d1, ref MyStruct d2)
{
}
Now call this function as
MyClass a = new MyClass();
MyClass b = null
int c = 3;
MyStruct d = new MyStruct();
Foo(a, ref a, b, c, d, ref d);
Here's what you get inside of the function:
void Foo(MyClass a1, ref MyClass a2,
out MyClass b1,
int c1,
MyStruct d1, ref MyStruct d2)
{
a1 is a copy in memory of the pointer to the instantiated class a;
a2 is the pointer to the instantiated class a;
b1 is the pointer to b, but has the additional check of having to be set within this function - and cannot be used before being set;
c1 is a copy in memory of the variable c;
d1 is a copy in memory of the struct d;
d2 is the struct d;
}
Important things to realize:
setting a1 to null will not set a to null.
setting a2 to null will set a to null.
setting b1 is required.
setting c1 will not change c.
setting d1 will not change d.
setting d2 will change d.
This allows for some weirdness like this:
void Foo(MyClass x, ref MyClass y)
{
x = null;
y.Bar("hi");
}
Called like:
MyClass a = new MyClass();
Foo(a, ref a);
You are using a class, and so your situation is more like variable a1 in the function call. Which means ref isn't strictly required.
The Jon Skeet article won't help you that much because his example with IntHolder is a struct not a class. Struct is value type like int and must be handled the same way.
In the two snippets you posted there is no need to pass list by ref. To quote Jon Skeet, object references are passed by value. This means, you would want to ref a reference type when the method will or might change the object reference and you want this new reference to carry back to the calling method. For example:
void methodA(string test)
{
test = "Hello World";
}
void methodB(ref string test)
{
test = "Hello World";
}
void Runner()
{
string first= "string";
methodA(first);
string second= "string";
methodB(ref second);
Console.WriteLine((first == second).ToString()); //this would print false
}
I am adding this answer for programmers that are used to C++ like myself.
Classes, interfaces, delegatess and arrays are reference types, meaning that they have an underlying pointer. Normal function calls copy this pointer(reference) by value, while sending by reference sends sends a reference to this reference:
//C# code:
void Foo(ClassA input)
void Bar(ClassA ref input)
//equivalent C++ code:
void Foo(ClassA* input)
void Bar(ClassA*& input)
Primitives such as int, double, etc structs and strings(string are an exception to these, but works similar), are allocated on the heap, so things work a bit different:
//C# code:
void Foo(StructA input)
void Bar(StructA ref input)
//equivalent C++ code:
void Foo(StructA input)
void Bar(StructA& input)
the ref keyword needs to be used both in declaration of the method and when calling it, so it would be clear it is referenced:
//C# code:
void Foobar(ClassB ref input)
...
ClassB instance = new ClassB();
Foobar(ref instance);
//equivalent C++ code:
void Foobar(ClassB*& input)
...
ClassB instance* = new ClassB();
Foobar(instance);
As said before, please read this detailed explanation. It also explains about strings.
It is interesting to note that calling by reference works with an underlying pointer, so we get to this code:
//C# code:
void Foo(ClassA input){
input = input + 3;
}
void Bar(ClassA ref input){
input = input + 3;
}
//equivalent C++ code:
void Foo(ClassA& input){
input = input + 3;
}
void Bar(ClassA*& input){
*input = *input + 3;
}
//equivalent pure C code:
void Fun(ClassA* input){
*input = *input + 3;
}
void Fun(ClassA** input){
*(*input) = *(*input) + 3;
}
it's a rough equivalent, but it's somewhat true.
No you don't need to use ref.
LinkedList is an object, so it is already a reference type. The parameter list is a reference to the LinkedList object.
See this MSDN article for a description of value types. Value types are usually the parameters you would use the ref or out keywords with.
You may also want to pass reference types by ref. This will allow you to point the reference to another object.
Any time you pass an object o you are really passing a reference to the object. When you pass a `ref object o' you are passing a reference to the reference. This allows to you modify the reference.
Passing Reference-Type Parameters may also help you understand.