This question already has answers here:
What's the difference between the 'ref' and 'out' keywords?
(28 answers)
Closed 7 years ago.
I thought I understood the difference, but now I'm not so sure. I've read the technical answer several times but I'm not understanding what is happening. I have this example.
class Program
{
static void Main()
{
int val = 0;
Example1(val);
Console.WriteLine(val); // Still 0!
Example2(ref val);
Console.WriteLine(val); // Now 2!
Example3(out val);
Console.WriteLine(val); // Now 3!
}
static void Example1(int value)
{
value = 1;
}
static void Example2(ref int value)
{
value = 2;
}
static void Example3(out int value)
{
value = 3;
}
}
I always thought the difference between default parameters is that if I am passing val into Example1, I can't use assignment.
But with the ref keyword val is still 0, but I have created a reference that is now treated as the variable "value" within Example2(ref val). Am I getting hung up on anything so far? if I had used
int value = 0;
Example1(value);
Console.WriteLine(value); // this would then return 1 correct?
Now then, what is happening with the out keyword? Same thing as ref?
See if this helps:
No "decorators"
static void Example(int value)
{
Console.WriteLine("Value is {0}", value);
value = 99;
}
usage
{
int value = 10;
Example(notADefaultValue); // Will print <Value is 10>
Console.WriteLine("Value is {0}", value); // will print <Value is 10>
}
Summary: Value types (structs/enums/int/double/etc) are not passed in as a reference by default so whatever you do to the variable within a method does not affect the caller. Thus, the "ref" keyword. If you pass a reference type to a method (i.e. a class) and change it's internals, these will affect the caller.
Default parameters:
static void Example(int value = 5)
{
Console.WriteLine("Value is {0}", value);
}
usage
{
int notADefaultValue = 10;
Example(notADefaultValue); // Will print <Value is 10>
Example(); // will print <Value is 5>
}
Summary: Default values allow you to call a method without explicitly needing to pass parameters, the default value is used.
Ref parameters:
static void Example(ref int value)
{
Console.WriteLine("Value is {0}", value);
value = 99;
}
usage
{
int value = 10;
Example(ref value); // Will print <Value is 10>
Console.WriteLine("Value is {0}", value); // Will print <Value is 99>
}
Summary: If you pass a value type in as a ref (reference) the value itself gets changed. Allreference types are passed in as ref by default. FYI, int is a primitive types so needs an explicit "ref".
out parameters:
static void Example(out int value)
{
value = 99;
Console.WriteLine("Value is {0}", value);
}
usage
{
int value; // no need to init it
Example(out value); // Will print <Value is 99>
Console.WriteLine("Value is {0}", value); // Will print <Value is 99>
}
Summary: Out parameters are like return variables but passed in via the signature of the method. Most common example is TryParse where the method returns vital information and depending on that information the out parameter is either valid or not (valid if it is true).
In the first example you do not specify that the variable is a reference, and because it is a fundamental type, it just copies the provided number. So value inside Example1 is a copy of value in Main.
The second example uses a reference. This means the both inside the function Example2 and inside Main are refering to the same place in the memory, and therefore the value is transfered, when both entering and exiting the function.
In the third example, the out keyword does the same as the second except that is initialized to be 0 when entered into the function. As a result, it is just a parameter for returning some kind of data. The value is just transfered when exiting the function.
Ok, its a duplicate of the linked question in the comments but I'll try to explain it for you.
Undecorated Parameters
Case A: public void MyFunc(int x) { }
-or-
Case B: public void MyFunc(MyClass y) { }
In Case A, the parameter is a value type, and value types are, by default, passed as copies of the original value to the function. This doesn't mean you aren't allowed to modify the value, but the value will not be reflected back at the calling location. This is the same for all value types, the value is copied before it is passed to the function.
In Case B, the parameter is a reference type. These types are passed by default as they are. They are not copied, but you are not allowed to change the reference (by assigning a new or null value to the type). You can change the contents of the object (any property/field there-of) and it will be reflected back in the calling location.
The ref keyword
Case A: public void MyFunc(ref int x) { }
-or-
Case B: public void MyFunc(ref MyClass x) { }
In case A, you are telling the compiler that you want to pass the value by reference, which means the compiler will not copy the type, but passes a reference to that type. The function is allowed to change it.
In case B, you are telling the compiler that the function is allowed to change where the reference points to (you can create a new or set it to null and it will be reflected in the calling site.
The out keyword
Case A: public void MyFunc(out int x) { }
-or-
Case B: public void MyFunc(out MyClass x) { }
Here, you are basically defining additional return types for the function. Its the method parameter telling the caller to expect a result in the place of the x variable. This is the same for both. The caller should not expect, in any case, that any value that x was before, will be the same afterwards. In fact you can expect that it will not be the same, because the method is required to assign a new value to x before it is allowed to return.
out basically means you provide a place for a return value, for value types just use the default constructor and for reference types initialize the value to null before you pass it in.
Related
I have seen a couple of the example on internet stated that I have to reset the stream by
stream.Seek(0, SeekOrigin.Begin);
However, if I pass the stream into a method as
public static bool ValidateStreamLine(Stream stream)
Do I have to still reset the stream?
Understand that on usual case if I pass in int, string, float or any other general variable type as
public static bool ValidateInt(int i)
the value of int i would not change.
Would that be any difference of the nature of Pass-by Value method on how the method react to stream?
You seem to be misunderstanding how arguments are passed in C#. By default, all arguments are passed by value in C#. In order to pass them by reference you need to use a special keyword: ref or out the latter being normally used when the argument is used as a second output of a given method. (See int.TryPase for example).
The important thing to understand here is that arguments passed by value behave quite diferently if the type of the argument is a reference type or a value type. This is where you seem to be confused.
To understand how it all works, make sure you are clear on the following:
Variables hold values.
The value of a variable whose type is a value type, is the value type's instance itself:
int i = 1 // i holds the value 1
The value of a variable whose type is a reference type is not the instance of said type. The value is the memory address where that instance lives.
string s = "Hello!" // s does not hold "Hello!" it holds a number that points to a place in memory where the string "Hello!" lives.
So, now that we are clear on that, what happens when you pass arguments by value (C#'s default)? What happens is that a copy of the variable is made and the copy is passed to the method.
If the type is a reference type, what is really copied and passed to the method is the value stored in the variable. And what is that? The memory address where the object referenced by the variable lives. So you see what happens? Both the original variable and the copied variable both point to the same object:
public class Foo
{
var frobbed = false;
public bool Frobbed { get { return frobbed; } }
public void Frob() { frobbed = true; }
}
void Frob(Foo foo) { foo.Frob(); }
var myFoo = new Foo();
Frob(myFoo);
Console.WriteLine(myFoo.Frobbed); //Outputs True! Why? Because myFoo and foo both point to the same object! The value of both variables (memory address) is the same!
If the type is a value type, the value itself of the value type is copied and handed to the method so there is no way the method can modify the value type stored in the original variable.
public void Increment(int i) { i = i + 1; }
var myInt = 1;
Increment(myInt);
Console.WriteLine(myInt); //Outputs 1, not 2. Why? i holds its own copy of 1, it knows nothing about the copy of 1 stored in myInt.
Things change when you pass arguments by reference. Now, the argument passed to the method is not a copy, its the original variable itself. A logical question follows; does this actually change anything in how reference types behave? The answer is yes, quite a lot:
public void ByValueCall(string s)
{
s = "Goodbye";
}
public void ByReferenceCall(ref string s)
{
s = "Goodbye";
}
var myString = "Hello!";
Console.WriteLine(ByValueCall(myString )); //outputs "Hello!"
Console.WriteLine(ByValueCall(myString )); //outputs "Goodbye!"
This behavior is identical with value types too. What is happening here?
When you pass an argument by value, the method gets a copy of the variable; therefore assigning a new value to the argument is really just assigning a new value to the copy; the original variable at the callsite doesn't care that you change the value of it's copy, be it a value type or a reference type. It will keep holding the value it always had.
When passing an argument by reference, you are not passing a copy, you are passing the variable itself. In that case assigning a new value to the variable will persist at the callsite. A canonical example is the following swap method:
public void Swap(ref int a, ref int b)
{
var temp = a;
a = b;
b = temp;
}
var i1 = 1;
var i2 = 2;
Swap(ref i1, ref i2);
var b = i1 == 2; //true
b = i2 == 1; //true
So after all of this, you should understand why the following behaves the way it does:
public ResetStream(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
}
var myStream = new ...
myStream.Read(bytes, 0, 1024);
ResetStream(myStream);
var isAtOrigin = myStream.Position == 0; //Returns true!
I have been making an effort on C# methods. There are three ways that parameters can be passed to a C# methods.
Value parameters : This method copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument.
Reference parameters : This method copies the reference to the memory location of an argument into the formal parameter. This means that changes made to the parameter affect the argument.
Output parameters : This method helps in returning more than one value.
I understood above types of passing parameters with below sample codes.
using System;
namespace PassingParameterByReference
{
class MethodWithReferenceParameters
{
public void swap(ref int x)
{
int temp = 5;
x = temp;
}
static void Main(string[] args)
{
MethodWithReferenceParameters n = new MethodWithReferenceParameters();
/* local variable definition */
int a = 100;
Console.WriteLine("Before swap, value of a : {0}", a);
/* calling a function to swap the value*/
n.swap(ref a);
Console.WriteLine("After swap, value of a : {0}", a);
Console.ReadLine();
}
}
}
When the above code is compiled and executed, it produces the following result:
Before swap, value of a : 100
After swap, value of a : 5
With this codes i could understand to pass parameters to methods by reference. And then i examine below code to understand passing parameters to methods by output.
using System;
namespace PassingParameterByOutput
{
class MethodWithOutputParameters
{
public void swap(out int x)
{
int temp = 5;
x = temp;
}
static void Main(string[] args)
{
MethodWithOutputParameters n = new MethodWithOutputParameters();
/* local variable definition */
int a = 100;
Console.WriteLine("Before swap, value of a : {0}", a);
/* calling a function to swap the value */
n.swap(out a);
Console.WriteLine("After swap, value of a : {0}", a);
Console.ReadLine();
}
}
}
When the above code is compiled and executed, it produces the following result:
Before swap, value of a : 100
After swap, value of a : 5
These sample codes make same action with different ways. And i can't understand difference between two approaches.( Passing Parameters To Method By Output And By Reference). Two example's output is the same. What is this small difference?
Output parameters dont have to be initialized before the method is called like it is the case for reference parameters.
int someNum;
someMethod(out someNum); //works
someMethod(ref someNum); //gives compilation error
Furthermore, the Output parameter needs to be set or changed within the method, which is not necessary for reference parameters.
With "Reference" parameters, the value needs to be assigned before a method can use it. X and Y in your examples would have needed to have been declared outside the method.
e.g. int x = 100; int y =200;
With "Output" parameters, the value for your parameters don't have to be assigned a value before you can use them. X and Y could have been declared in your example with no starting values assigned to them.
e.g int x; int y;
Reference and Output parameters are very similar.
The only difference is that ref parameters must be initialized.
int myInt = 1;
SomeMethod(ref myInt); //will work
SomeMethod(out myInt); //will work
int myInt;
SomeMethod(ref myInt); //won't work
SomeMethod(out myInt); //will work
The compiler will actually view the ref and out keywords the same. For example if you cannot have overloaded methods where the only difference is the ref and out keywords.
The following methods signatures will be viewed the same by the compiler, so this would not be a valid overload.
private void SomeMethod(ref int Foo){};
private void SomeMethod(out int Foo){};
An output parameter needs to have it's value changed inside the method otherwise the compiler will throw an error.
The reference parameter may or may not have it's reference (reference objects) changed by the method.
Also value types (types defined in structs) cannot be passed by reference.
See this What's the difference between the 'ref' and 'out' keywords?
The difference is that for an out parameter you have to set it before leaving the method. So even if you dont set it to any value before calling the method the compiler knows that it will get a value during the method call.
Appart from technical differences, to have a good readable code, you should use out when the method has more than one output. And use ref when the method just may update the variable
When I declare a method with parameters, and inside my method I assign value to those parameters, those parameters turn into variables?
My question is, can I Say: "The parameter of my method is also a variable when I use it inside my method"?
Example:
public int returnDays(int month)
{
month = getMonth();
//"Can I say : month is a variable?"
}
//"Can I say : month is a variable?"
yes it is a local variable to that method.
Official docs on passing arguments
Yes it is called variable and you can call it variable and you can use it. Variable is a named place holder in memory whoes value could be changed in program
In computer programming, a variable is a storage location and an
associated symbolic name (an identifier) which contains some known or
unknown quantity or information, a value. The variable name is the
usual way to reference the stored value; this separation of name and
content allows the name to be used independently of the exact
information it represents. The identifier in computer source code can
be bound to a value during run time, and the value of the variable may
thus change during the course of program execution, reference.
You have 2 questions
I declare a method with parameters, and inside my method I assign
value to those parameters, those parameters turn into variables
Short Answer YES they are variables
can I call variables to the parameters of the method when I use them
inside my method
As far as your context is concerned Yes you can use them but in a broader perspective what variables are accessible to you inside the method scope you should read this before going in to development details
I don't entirely get your question. Yes, "month" is a variable. However, I'm unsure on what you're trying to achieve by assigning it.
The int type derives from struct, and this means that it isn't passed by reference. When you call returnDays(x), x itself isn't passed and a copy of it is made.
If you, instead, wanted to change its value AND return the days, you'd need to use the ref or out keywords. The former basically passes a pointer to x, which can be used as your function pleases. The latter, however, is stricter and requires the function to initialize whatever value is passed through it.
So, this is the code you'd end up with
public int ReturnDays(out int month)
{
month = GetCurrentMonth();
return GetDays(month);
}
But still, I am not sure if this is the kind of answer you wanted.
First of all, is this C# or Java? Each language has its own eccentricities.
If C# use the out statement that KappaG3 showed.
If Java,
just use a return statement inside your function/method:
return getMonth();
If you need to return multiple values, you can pass objects and then assign to those objects inside the function/method. Objects are passed by reference where as primitives are passed by value. integer is an Object but doesn't act like one as you can see from:
//
public class Main {
public static void main(String[] args) {
int value1 = 0;
Integer value2 = new Integer(0);
MyObject value3 = (new Main()).new MyObject(0);
passByVal(value1);
passByRef(value2);
passByRef(value3);
System.out.println("value1 = " + value1);
System.out.println("value2 = " + value2);
System.out.println("value3 = " + value3);
}
class MyObject
{
public int value = 0;
public MyObject(int value) { this.value = value; }
#Override
public String toString() {
return value + "";
}
}
public static void passByVal(int i)
{
i = 7;
}
public static void passByRef(Integer i)
{
i = new Integer(7);
}
public static void passByRef(MyObject o)
{
o.value = 7;
}
}
which return the output:
0
0
7
so if you need to return a bunch of values I recommend passing objects or returning an object that is specially designed to hold all those values
In C++, I have a function:
void MyFunction(int p)
{
p=5;
}
Assume, I have:
int x = 10;
MyFunction(x); // x = 10
MyFunction(&x); // x = 5
How to archieve this in C# with condition: I create only one MyFunction.
Your C++ function doesn't work the way you think it does. In fact, your code will not compile.
In C#, you would use the ref or out keywords:
void MyFunction1(out int p)
{
p = 5;
}
void MyFunction2(ref int p)
{
p = p + 1;
}
int x;
MyFunction1(out x); // x == 5
MyFunction2(ref x); // x == 6
In C# you would need to declare the method with a ref parameter, like this:
void MyFunction(ref int p)
{
p=5;
}
If you then call it as MyFunction(ref x) the value of x in the caller will be modified. If you don't want it to be modified simply copy it to a dummy variable. You could create an overload of MyFunction that does this internally:
void MyFunction(int p)
{
MyFunction(ref p);
}
It would technically not be "one function", as you want, but the code wouldn't be duplicated and to any human reading your code it would appear as one - but to the compiler it's two. You would call them like this:
int x = 10;
MyFunction(x); // x = 10
MyFunction(ref x); // x = 5
C# does not have the equivalent functionality. If you declare the method to have a ref parameter, then you must also specify that the parameter is ref type when you call the method.
You need to pass the parameter as reference. If you don't specify it, it automatically creates a copy to work inside the parameter instead of using the same reference.
How to do that? Just specify with the 'ref' word in method declaration:
void MyFunction(ref int p)
{
p=5;
}
int x = 10;
MyFunction(ref x); // x = 5
The point is that a lot of people think that Reference types are passed by reference and Value types are passed By Value. This is the case from a user's perspective, internally both Reference and Value types are passed By Value only.
When a Reference type is passed as a parameter, its value, which is a reference to the actual object is passed. In case of Value types, their value is the value itself (e.g. 5).
StringBuilder sb = new StringBuilder();
SetNull(sb);
SetNull(ref sb);
if SetNull(...) sets the parameter to null, then the second call will set the passed in StringBuilder parameter to null.
Can you please tell me what is the exact use of out parameter?
Related Question:
What is the difference between ref and out? (C#)
The best example of a good use of an out parameter are in the TryParse methods.
int result =-1;
if (!Int32.TryParse(SomeString, out result){
// log bad input
}
return result;
Using TryParse instead of ParseInt removes the need to handle exceptions and makes the code much more elegant.
The out parameter essentially allows for more than one return values from a method.
The out method parameter keyword on a
method parameter causes a method to
refer to the same variable that was
passed into the method. Any changes
made to the parameter in the method
will be reflected in that variable
when control passes back to the
calling method.
Declaring an out method is useful when
you want a method to return multiple
values. A method that uses an out
parameter can still return a value. A
method can have more than one out
parameter.
To use an out parameter, the argument
must explicitly be passed to the
method as an out argument. The value
of an out argument will not be passed
to the out parameter.
A variable passed as an out argument
need not be initialized. However, the
out parameter must be assigned a value
before the method returns.
An Example:
using System;
public class MyClass
{
public static int TestOut(out char i)
{
i = 'b';
return -1;
}
public static void Main()
{
char i; // variable need not be initialized
Console.WriteLine(TestOut(out i));
Console.WriteLine(i);
}
}
http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
Out parameters are output only parameters meaning they can only passback a value from a function.We create a "out" parameter by preceding the parameter data type with the out modifier. When ever a "out" parameter is passed only an unassigned reference is passed to the function.
using System;
class ParameterTest
{
static void Mymethod(out int Param1)
{
Param1=100;
}
static void Main()
{
int Myvalue=5;
MyMethod(Myvalue);
Console.WriteLine(out Myvalue);
}
}
Output of the above program would be 100 since the value of the "out" parameter is passed back to the calling part. Note
The modifier "out" should precede the parameter being passed even in the calling part. "out" parameters cannot be used within the function before assigning a value to it. A value should be assigned to the "out" parameter before the method returns.
Besides allowing you to have multiple return values, another use is to reduce overhead when copying a large value type to a method. When you pass something to a method, a copy of the value of that something is made. If it's a reference type (string for example) then a copy of the reference (the value of a reference type) is made. However, when you copy a value type (a struct like int or double) a copy of the entire thing is made (the value of a value type is the thing itself). Now, a reference is 4 bytes (on 32-bit applications) and an int is 4 bytes, so the copying is not a problem. However, it's possible to have very large value types and while that's not recommended, it might be needed sometimes. And when you have a value type of say, 64 bytes, the cost of copying it to methods is prohibitive (especially when you use such a large struct for performance reasons in the first place). When you use out, no copy of the object is made, you simply refer to the same thing.
public struct BigStruct
{
public int A, B, C, D, E, F, G, H, J, J, K, L, M, N, O, P;
}
SomeMethod(instanceOfBigStruct); // A copy is made of this 64-byte struct.
SomeOtherMethod(out instanceOfBigStruct); // No copy is made
A second use directly in line with this is that, because you don't make a copy of the struct, but refer to the same thing in the method as you do outside of the method, any changes made to the object inside the method, are persisted outside the method. This is already the case in a reference type, but not in value types.
Some examples:
public void ReferenceExample(SomeReferenceType s)
{
s.SomeProperty = "a string"; // The change is persisted to outside of the method
}
public void ValueTypeExample(BigStruct b)
{
b.A = 5; // Has no effect on the original BigStruct that you passed into the method, because b is a copy!
}
public void ValueTypeExampleOut(out BigStruct b)
{
b = new BigStruct();
b.A = 5; // Works, because you refer to the same thing here
}
Now, you may have noticed that inside ValueTypeExampleOut I made a new instance of BigStruct. That is because, if you use out, you must assign the variable to something before you exit the method.
There is however, another keyword, ref which is identical except that you are not forced to assign it within the method. However, that also means you can't pass in an unassigned variable, which would make that nice Try.. pattern not compile when used with ref.
int a;
if(TrySomething(out a)) {}
That works because TrySomething is forced to assign something to a.
int a;
if(TrySomething(ref a)) {}
This won't work because a is unassigned (just declared) and ref requires that you only use it with an assigned variable.
This works because a is assigned:
int a = 0;
if(TrySomething(ref a)) {}
However, in both cases (ref and out) any changes made to a within the TrySomething method are persisted to a.
As I already said, changes made to a reference type are persisted outside the method in which you make them, because through the reference, you refer to the same thing.
However, this doesn't do anything:
public void Example(SomeReferenceType s)
{
s = null;
}
Here, you just set the copy of a reference to s to null, which only exists within the scope of the method. It has zero effect on whatever you passed into the method.
If you want to do this, for whatever reason, use this:
public void Example1(ref SomeReferenceType s)
{
s = null; // Sets whatever you passed into the method to null
}
I think this covers all use-cases of out and ref.
from http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
One way to think of out parameters is that they are like additional return values of a method. They are very convenient when a method returns more than one value, in this example firstName and lastName. Out parameters can be abused however. As a matter of good programming style if you find yourself writing a method with many out parameters then you should think about refactoring your code. One possible solution is to package all the return values into a single struct.
In contrast ref parameters are considered initially assigned by the callee. As such, the callee is not required to assign to the ref parameter before use. Ref parameters are passed both into and out of a method.
The typical use case is a method that needs to return more than one thing, so it can't just use the return value. Commonly, the return value is used for a success flag while the out parameter(s) sets values when the method is successful.
The classic example is:
public bool TryGet(
string key,
out string value
)
If it returns true, then value is set. Otherwise, it's not. This lets you write code such as:
string value;
if (!lookupDictionary.TryGet("some key", out value))
value = "default";
Note that this doesn't require you to call Contains before using an indexer, which makes it faster and cleaner. I should also add that, unlike the very similar ref modifier, the compiler won't complain if the out parameter was never initialized.
In simple words pass any variable to the function by reference so that any changes made to that variable in side that function will be persistent when function returns from execution.
Jon Skeet describes the different ways of passing parameters in great detail in this article. In short, an out parameter is a parameter that is passed uninitialized to a method. That method is then required to initialize the parameter before any possible return.
generally we cannot get the variables inside a function if we don't get by a return value.
but use keyword "out" we can change it value by a function.