I'm learning C# with Yellow Book. In the chapter 3.1.9, when describing differences between passing parameter values as ref vs out, it says the following:
When you pass a parameter as a reference you are giving the method complete control of it. Sometimes you don't want this. Instead you want to just allow the method to change the variable.
If I am the one coding the method, i.e. its behavior, how am I giving it complete control of it?
It doesn't mean it is less secure, it just means the method "has control over your variable" that you are passing as parameter for "processing". It can potentially return a completely new object and not the one you "provided". More can be found here:
When used in a method's parameter list, the ref keyword indicates that an argument is passed by reference, not by value. The ref keyword makes the formal parameter an alias for the argument, which must be a variable. In other words, any operation on the parameter is made on the argument.
For example, suppose the caller passes a local variable. The called method can then replace the object to which the ref parameter refers. In that case, the caller's local variable or the array element refers to the new object when the method returns.
Related
Are BigIntegers in C# passed by value or by reference? I am having a code in which I need to pass them by value and I think they are passed as reference personally, as the value is changed after some calls in initial calling function, not sure though if it is the case actually.
Please help :)
Technically speaking, all objects in C# (and Java as well) are passed by value (by default).
For reference types, this value happens to be a reference (pointer). That's why changes inside the method affects the actual object.
For value types, this value is the actual value the variable holds. That's why changes inside the method doesn't affect the actual object.
BigInteger is not special in anyway, it's a struct (which is a value type).
If you want to pass an object by reference, you can use ref keyword.
See also:
Passing Reference-Type Parameters (C# Programming Guide)
Passing Value-Type Parameters (C# Programming Guide)
You may also want to give a look at the answers for this question.
BigInteger is a struct, so it is a value type and it is passed by value by default:
Because a struct is a value type, when you pass a struct by value to a method, the method receives and operates on a copy of the struct argument. The method has no access to the original struct in the calling method and therefore can't change it in any way. The method can change only the copy.
Passing Value-Type Parameters (C# Programming Guide)
A value-type variable contains its data directly as opposed to a reference-type variable, which contains a reference to its data. Passing a value-type variable to a method by value means passing a copy of the variable to the method. Any changes to the parameter that take place inside the method have no effect on the original data stored in the argument variable. If you want the called method to change the value of the argument, you must pass it by reference, using the ref or out keyword. You may also use the in keyword to pass a value parameter by reference to avoid the copy while guaranteeing that the value will not be changed. For simplicity, the following examples use ref.
If you want to pass such type by reference, you can use the ref keyword.
Passing Reference-Type Parameters (C# Programming Guide)
A variable of a reference type does not contain its data directly; it contains a reference to its data. When you pass a reference-type parameter by value, it is possible to change the data belonging to the referenced object, such as the value of a class member. However, you cannot change the value of the reference itself; for example, you cannot use the same reference to allocate memory for a new object and have it persist outside the method. To do that, pass the parameter using the ref or out keyword. For simplicity, the following examples use ref.
It will therefore be only the memory pointer (4 or 8 bytes on x32 or x64 systems) which is pushed into the stack before the call of a method (like an instance of a class) instead of the entire structure content (the copy of all members, for example 8x4 bytes if the struct has 8 integers, at least).
Pass c# struct by reference
Passing a struct by Reference
Pass reference by reference vs pass reference by value - C#
Passing a Reference vs. Value (Pluralsight)
Understanding C# Pass by Reference and Pass by Value (Udemy)
Passing Arguments By Value and By Reference (C# 6 for Programmers, 6th Edition)
There are many examples, let's take array copy method as an example. The signature of the Array.Copy is method is as below
public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length);
Judging only from signature, one can not tell that the sourceArray will not be changed while the destinationArray will be altered, even if it is some thing as simple as an array of Int. The guarantee coming from the keyword "ref" for programmers have lost here.
It seems to me that the the destinationArray parameter should better be marked as "ref Array". If it had been done this way, the syntax would be more consistent with the usage of the keyword "ref", indicating that the passed in object might be modified by the callee and the change is visible for the caller. The only benefit I can think of concerning mitting the keyword "ref", is that saves a few key strokes. or it is just mimicking the C/C++ style without much thinking.
My question is: what are some seasonings behind this design decision?
Update: For the record, I am advocating that an array be of the same value/reference category as its elements, thus making a clear extinction between Fun(array) and Fun(ref array), that is the same guarantee programmers get with Fun(int) and Fun(ref int). Optimization for efficiency can be left to the implementation level.
Array is a reference type. You can pass references by value and the instances they reference will still be the same ones that get modified. The callee is modifying the same instance using its own reference to it and has no reason to change it into a completely different instance entirely (which is where ref would actually come into use).
There isn't any convention that states to use ref when passing reference types — you generally don't need to most of the time, except as mentioned if your method actually intends to change the instance entirely like so:
class Foo { public int Value; }
public static void ReplaceFoo(ref Foo foo)
{
foo = new Foo { Value = 2 };
}
var foo = new Foo { Value = 1 };
Console.WriteLine(foo.Value);
ReplaceFoo(ref foo);
Console.WriteLine(foo.Value);
Judging only from signature, one can not tell that the sourceArray will not be changed while the destinationArray will be altered
Why is this a problem? No one reads APIs only paying attention to method signatures and ignoring parameter names. Signatures are there for the compiler to distinguish overloads. Anyone reading the API for Array.Copy() would understand that sourceArray is going to be unchanged, being where the method is getting the values from, and destinationArray is going to be modified, being the one receiving the values — unless they don't speak English (which is fine, but most APIs are written in English).
The only other scenario I can think of where a reader would be confused is if they didn't have the prior knowledge that arrays are reference types in .NET. But misusing ref in a situation where it's not needed at best and inappropriate at worst doesn't solve that problem.
C# (and .NET) include both reference types and value types.
Normally (absent ref or out keywords), parameters are passed to methods by value. So, if you pass an integer to a function, the value of the integer is passed. If you put a a variable referring to an array in a function call (remembering that all arrays are instances of the reference type System.Array), the value of that variable, i.e., the reference to to the array, is passed to the function.
So, within the function, the code gets to play on that array. When the function returns, that variable (in the scope of the caller) still refers to that same object. However, the function may have mutated that array, so the variable (in the caller scope) may be referring to a changed object.
If you pass a value type by reference (with the ref keyword), the function can change the value of the parameter, and when the function returns, the variable (in the caller scope) will receive the new value.
But, if you use ref (or out) on a parameter of reference type, you are passing a reference by reference. So, for example, you could pass in an array of five integers and the function could assign that parameter and array of ten integers (they are of the same type, but definitely differentobjects). In the caller, when the function returns, the variable associated with that parameter will see what it refers to completely change during the call.
In your example, the caller will instantiate two arrays of the same type and compatible lengths (usually the same length if the source and destination indexes are 0 and the length is sourceArray.Length). The function does not change what object the destination array parameter refers to, it just fills the destination from the source.
In fact, if the destination was by ref, it wouldn't be as flexible. Consider a case where the destination is 30 entries long, and your intention is to fill the middle ten array entries with the source. It just works. It wouldn't with a ref destination parameter (without a lot more work).
The reason for omitting the ref keyword is that in most cases, it won't make any difference to include it, so it's superfluous. However, it does actually make a difference in some cases. An array is a reference type, and that means a value representing that reference gets passed. Normally, updating the passed in value will trigger updates to the original object. BUT if you create a NEW array and assign the passed in parameter to the new item, the reference gets lost - whereas the ref keyword preserves it.
I was recently reading an answer about CS1628, "Cannot use ref or out parameter 'parameter' inside an anonymous method, lambda expression, or query expression".
The answer stated a way around this is to implement "ref parameters as boxes" in the CLR.
C# compiler error CS1628 with VS2010/C#4
I am unsure what this means and seem to be unable to find any references to it in google.
Can anyone please explain this to me as its way over my head?
You can declare a "box" class:
class Box<T> { public T Value; }
Pass an instance of that class to the method that you cannot use ref with. The method can reach into the object and mutate Value. The caller can later extract Value.
This works (in constrast to ref) because Box is allocated on the heap and has "infinite" lifetime. ref can only refer to locations with more restricted lifetime.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Read-only (“const”-like) function parameters of C#
Why is there no const member method in C# and const parameter?
Having programmed in C++ in the past, I recall we could make a constant reference/pointer parameter in a method.
If my memory is correct, the below means, that the method cannot alter the reference and the reference itself is a constant reference.
C++ example
void DisplayData(const string &value) const
{
std::count << value << endl;
}
Is there an equivalent in C# for methods in a class?
The reason why I'm asking is, I'm trying to pass a object by reference (for speed) and at the same time don't want anyone to alter it.
Update 16/09/2020
There now appears to be the in parameter modifier that exhibits this behaviour (in essence, a ref readonly). A brief search on when you would ever use this yields the following answer:
Why would one ever use the "in" parameter modifier in C#?
Original Answer
There is no equivalent for C# and it has been asked many, many, many, many times before.
If you don't want anyone to alter the "reference", or perhaps you mean the content of the object, make sure the class doesn't expose any public setters or methods of mutating the class. If you cannot change the class, have it implement an interface that only publicly exposes the members in a read-only fashion and pass the interface reference instead.
If you mean you want to stop the method from changing the reference, then by default if you pass it "by reference", you are actually passing the reference by value. Any attempt from the method to change what the reference points to will only affect the local method copy, not the caller's copy. This can be changed by using the ref keyword on a reference type, at which point the method can point the reference at a new underlying object and it will affect the caller.
For value types (int, double, byte, char,...,struct) the arguments come in as values and therefore are guaranteed not to affect that calling module.
For string type, although it is a reference type, it is immutable by the CLR, such that nothing you do inside the procedure can affect the original string.
For other reference types (class) there is no way to guarantee changes in the class from the method.
A MS help page about the difference between pass-by-value and pass-by-reference seems quite clear to me:
http://msdn.microsoft.com/en-us/library/8b0bdca4.aspx
However, a user comment at the end has confused me somewhat. It says (among other things) this:
if you don‘t use the ref or out keywords, then arguments to methods
are passed by value.
The comment seems quite wrong to me. Is it?
(I posted part of the comment out of context: Here's the full comment:)
The text says: "... but when a class instance is passed, a reference
is passed. ..." This is incorrect, as you can see in:
C# Language specification Version 4.0 (a Microsoft free download)
5.1.4 Value parameters A parameter declared without a ref or out
modifier is a value parameter.
So, in the example above, the class instance is passed by value, and
not by reference.
It is the full comment which is really confusing me... The class instance is passed by value and not by reference? Does that not imply that the instance bytes are pushed onto the stack?
The comment is true. Without ref or out, the variable is passed by value. However, with objects, what you are passing by value is a reference.
The only time you would want to pass an object-reference by reference is if you are assigning a new object to the parameter within the method and you want that reassignment to affect the caller's copy of the reference.
You aren't ever really passing an object around. Instead you are passing around references to an object. With that in mind, this byval/byref business applies to the object-reference, not the object itself.
Jon Skeet has a great post about this topic.
The complete comment is misleading. The object's reference is passed by value.
The comment is completely correct. The confusion here is that value types and reference types are pretty much unrelated to passing an argument by value or by reference.
When you pass a value type as a non-ref parameter, you pass its value. That's clear enough. For a reference type, though, you are still only passing a value: You are passing the value of the reference itself.
If the parameter is ref/out, though, then you are actually saying that the parameter is an alias for the variable that is actually being passed in. In that case, it doesn't matter if it's a value type or a reference type; a reference to the variable is being passed, not just a value.