I want to ask something about ref modifier.
What I know and understand:
With method that use ref modifier, there will be no copy of data as with passing by value, but parameter will have directly access to argument value. Basically said, all you done in method’s scope will act same as if you would done it with argument (passed variable) in caller’s scope.
and I want to ask what is exactly stored in parameter with ref modifier:
When I pass argument to method with ref modifier, will parameter contain reference to value of argument? or is it something else?
Thank you for your answers
When you have a parameter with the ref attribute, it passes the argument by reference and not value. That means a new copy of the variable is not being made, rather a pointer to the original is being used within your function.
public void Foo()
{
var x = 0;
Bar(x); // x still equals 0
Bar(ref x); // x now equals 1
}
public void Bar(ref int x)
{
x = 1;
}
public void Bar(int x)
{
x = 1;
}
Let's say we have this method:
public void DoSomething(int number)
{
number = 20;
}
And we use it:
var number = 10;
DoSomething(number);
Console.WriteLine("Our number is: {0}", number);
The output would be Our number is: 10. Our number does not become 20.
That's because we're passing by value, so we're basically taking a copy of number before we change it.
However, if we pass by reference instead:
public void DoSomething(ref int number)
{
number = 20;
}
And then use our method:
var number = 10;
DoSomething(ref number);
Console.WriteLine("Our number is: {0}", number);
The output then becomes Our number is: 20
Related
Suppose I have an initialized list: List<double> o
I'd like to perform the following:
int offset = 10;
for (int i = 0; i < o.Count; ++i){
o[i] = ApplyRamp(o[i]-offset)
}
where ApplyRamp is defined as:
public static void ApplyRamp(ref double x)
{
if (x < 0) x = 0;
}
But the code won't compile. Why isn't the single element of a List<double>, i.e. o[i], not treated as type double?
There are four problems here:
You have to use ref on the argument as well as the parameter
The expression o[i] - offset is classified as a value rather than a variable, so you can't pass it by reference
Even the expression o[i] would be classified as a value, as it's the result of calling an indexer. If o were a double[] (i.e. an array instead of a list) then o[i] would be classified as a variable.
You're trying to use the result of a void method as the right-hand side of an assignment operator. A void method doesn't have a result.
You could use:
double temp = o[i] - offset;
ApplyRamp(ref temp);
// Do something with temp?
But it's not clear what you'd do with temp afterwards anyway. Are you trying to modify o? If so, where does offset come in? And why would you be assigning to o[i] as well in that case?
Finally, I'd strongly urge you to consider making your ApplyRamp just use a regular by-value parameter and return the result instead. That will make it easier to use in most cases. I rarely see a good use of ref parameters in void methods.
So something like:
public static double ApplyRamp(double x)
{
return x < 0 ? 0 : x;
}
Or just use Math.Max:
public static double ApplyRamp(double x)
{
return Math.Max(x, 0);
}
You can't assign void to any variable, I think you should change signature of your method:
public static double ApplyRamp(double x)
{
if (x < 0) return 0;
return x;
}
Now your method will return double and will assign this value to o[i] element.
void type description
When used as the return type for a method, void specifies that the method doesn't return a value.
And obviously you want to return a value here. Because (as I suppose), you want to adjust x to be non-negative. So I think changing your code to return double is best way.
If you simply want to get a list with the same values, but decreased by offset or equal to 0 for values which are less than offset, you can use LINQ Select.
It will create a new List<double> by applying a calculating function to the every item in your o array, and then will assign this List back to o:
o = o.Select(x => x - offset < 0 ? 0 : x - offset).ToList();
or
o = o.Select(x => Math.Max(x - offset, 0)).ToList();
I have defined a function where one of the parameters is out. Here, when the function call is made, I pass either a an initialized or an uninitialized argument.
Now, in the case of an initialized argument, how do I make the callee not change the value of the out parameter?
I cant use a ref here because sometimes I do send an uninitialized argument.
Ex:
void fun1()
{
int x = 3;
fun2 (out x);
int y;
fun2(out y);
}
void fun2(out int x)
{
...
}
Here, I dont want the x to lose the value 3 once control goes to fun2.
From out C# - MSDN
Although variables passed as out arguments do not have to be initialized before being passed, the called method is required to assign a value before the method returns.
Since a value must be assigned to the parameter with out, you can't save the value in function. It would be better if you make a copy of the variable before calling the function. like:
int x = 1;
int backupX = x;
fun2(out x);
Maybe I get all wrong, but this sounds like you just want to define a method like this
void caller(){
int x=5;
int y = doSomething(x);
}
int doSomething(int x){
return x+1;
}
or in case you want a null state use:
void caller(){
int? x=5;
int y = doSomething(x);
}
int doSomething(int? x){
if (x == null)
return x;
return x+1;
}
In C#, when defining a public method like:
public int myMethod(String someString)
{
//code
}
What does the int indicate apart from the type integer? What confuses me is that the method is using a String as arguments in this case.
It is the return type of the method. In this case a 32-bit signed integer with a range of
-2,147,483,648 .. +2,147,483,647
It corresponds to the .NET type System.Int32. int is just a handy C# alias for it.
You would return a value like this
public int Square(int i)
{
return i * i;
}
And you could call it like this
int sqr = Square(7); // Returns 49
// Or
double d = Math.Sin(Square(3));
If you do not need the return value, you can safely ignore it.
int i;
Int32.TryParse("123", out i); // We ignore the `bool` return value here.
If you have no return value you would use the keyword void in place of the type. void is not a real type.
public void PrintSquare(int i)
{
Console.WriteLine(i * i);
}
And you would call it like this
PrintSquare(7);
The method in your example accepts a string as input parameter and returns an int as result. A practical example would be a method that counts the number of vowels in a string.
public int NumberOfVowels(string s)
{
const string vowels = "aeiouAEIOU";
int n = 0;
for (int i = 0; i < s.Length; i++) {
if (vowels.Contains(s[i])) {
n++;
}
}
return n;
}
It stands for "integer", and it means the method returns an integer number of 32 bits, also known in C# as Int32.
As previously stated, it's what the method returns.
For example:
public string x()
{
return 5;
}
Would error. 5 is definitely not a string!
public int x()
{
return 5;
}
Would be correct; since 5 can be considered an int (Short for integer, which is, basically, just a number which cannot have a decimal point. There's also float, double, long and decimal, which are worth reading about)
There must be no way of it not returning, for example, if you do:
public int x()
{
if (false)
{
return 5;
}
}
It will error because if the expression is false (It is of course) it won't be returning an int, it won't return anything.
If you use the keyword void, it means it does not return anything. Ex:
public void x()
{
someFunction("xyz");
}
It's fine that it doesn't return as it's a void method.
I don't think you're new to programming judging by your reputation, but just in case, when you return something you pass it back from the method, for example:
int x;
public int seven()
{
return 7;
}
x = seven();
x will become the return value of the function seven.
Note that the 'dynamic' type works here:
public dynamic x(int x, int y)
{
if (x == y)
{
return "hello";
}
return 5
}
But if you're new to C# don't get caught up in dynamic typing just yet. :)
It is the type of the return value.
Everyone is correct here but the definition from msdn:
"Int32 is an immutable value type that represents signed integers with values that range from negative 2,147,483,648 (which is represented by the Int32.MinValue constant) through positive 2,147,483,647 (which is represented by the Int32.MaxValue constant. The .NET Framework also includes an unsigned 32-bit integer value type, UInt32, which represents values that range from 0 to 4,294,967,295."
Found here on MSDN: Int32 Structure
I suggest you read the documentation found in the link above. It is extremely useful.
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Why use ref keyword when passing an Object?
When to pass ref keyword in
What is the correct usage of the 'ref' keyword in C#. I believe there has been plenty of discussion threads on this, but what is not clear to me is:
Is the ref keyword required if you are passing in a reference object? I mean when you create an object in the heap, is it not always passed by reference. Does this have to be explicitly marked as a ref?
Using ref means that the reference is passed to the function.
The default behaviour is that the function receives a new reference to the same object. This means if you change the value of the reference (e.g. set it to a new object) then you are no longer pointing to the original, source object. When you pass using ref then changing the value of the reference changes the source reference - because they are the same thing.
Consider this:
public class Thing
{
public string Property {get;set;}
}
public static void Go(Thing thing)
{
thing = new Thing();
thing.Property = "Changed";
}
public static void Go(ref Thing thing)
{
thing = new Thing();
thing.Property = "Changed";
}
Then if you run
var g = new Thing();
// this will not alter g
Go(g);
// this *will* alter g
Go(ref g);
There is a lot of confusing misinformation in the answers here. The easiest way to understand this is to abandon the idea that "ref" means "by reference". A better way to think about it is that "ref" means "I want this formal parameter on the callee side to be an alias for a particular variable on the caller side".
When you say
void M(ref int y) { y = 123; }
...
int x = 456;
M(ref x);
that is saying "during the call to M, the formal parameter y on the callee side is another name for the variable x on the caller side". Assigning 123 to y is exactly the same as assigning 123 to x because they are the same variable, a variable with two names.
That's all. Don't think about reference types or value types or whatever, don't think about passing by reference or passing by value. All "ref" means is "temporarily make a second name for this variable".
I believe the ref keyword indicates that you are passing the object by reference, not by value. For example:
void myfunction(ref object a) {
a = new Something();
}
would change the value of a in the calling function
However,
void myfunction(object a) {
a = new Something();
}
would change the value of a locally, but not in the calling function. You can still change PROPERTIES of the item, but you cannot set the value of the item itself. For example;
a.someproperty = value;
would work in both cases.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace InOutRef
{
static class InOutRef
{
public static void In(int i)
{
Console.WriteLine(i);
i=100;
Console.WriteLine(i);
}
public static void Ref(ref int i)
{
Console.WriteLine(i);
i=200;
Console.WriteLine(i);
}
public static void Out(out int i)
{
//Console.WriteLine(i); //Error Unsigned Ref
i=300;
Console.WriteLine(i);
}
}
class Program
{
static void Main(string[] args)
{
int i = 1;
InOutRef.In(i); //passed by value (in only)
Debug.Assert(i==1);
InOutRef.Ref(ref i); //passed by ref (in or out)
Debug.Assert(i == 200);
InOutRef.Out(out i); //passed by as out ref (out only)
Debug.Assert(i == 300);
}
}
}
I can't be any more literal on my answer. The code will not remember reference chanages such as the classic Java swap question when using in. However, when using ref, it will be similar to VB.NET as it will remember the changes in and out. If you use the out parameter it means that it must be declared before you return (this is enforced by the compiler).
Output:
1 //1 from main
100 //100 from in
1 //1 is NOT remembered from In
200 //200 from ref
//should be 200 here but out enforces out param (not printed because commented out)
300 //300 is out only
Press any key to continue . . .
Given the code below:
class Sample
{
public static void Run()
{
int i = 1;
Action<int> change = Increment();
for (int x = 0; x < 5; x++ )
{
change(i);
Console.WriteLine("value=" + i.ToString());
}
}
public static Action<int> Increment()
{
return delegate(int i) { i++; };
}
}
I get the answer:
value=1
value=1
value=1
value=1
value=1
value=1
Instead of 1, 2, 3 ... 6.
This is from an article on the net with links to clues but I can't work out why this is. Anyone have any ideas?
Your parameter is being passed by value.
Writing i++ will change the value of i to a different int value (unlike a mutable type).
When you write i++ inside the delegate, you're changing the parameter to be equal to a different int value. However, this does not affect the local variable whose value was copied to the parameter.
To solve this, you need to make a delegate with a ref parameter. ref parameters are passed by reference. Therefore, when you change a ref int parameter to a different int value, you'll also change the local variable or field whose reference was passed as the parameter.
For more information, see here.
Since the Action delegates do not take ref parameters, you'll need to make your own delegate type, like this:
delegate void RefAction<T>(ref T param);
The datatype int is a primitive data type and hence a value-type as opposed to a reference type. This means that when you pass variable i to a function it isn't the actual variable that has been passed but instead a copy of the value. And therefore when the parameter is changed inside the function it is the local copy that has been changed and no the original variable.
If you are certain you want the function to be able to modify the value of the original variable, then you should add the ref keyword to the function parameter signature to tell the compiler that you want to pass the variable as a reference.
public void ChangeOriginal(ref int something)
{ something = something + 1;}
public void ChangeLocalCopy(int something)
{something = something + 1;}
I suggest you read up upon the stack vs the heap (value-type vs reference-type) since it's a very fundamental subject when programming.
the Action returns nothing. Its only incrementing the value passed in - not the reference to the orginal (as Slaks says). You can use a Func to do in this way.
class Sample
{
public static void Run()
{
int i = 1;
Func<int, int> change = Increment();
for (int x = 0; x < 5; x++ )
{
i = change(i);
Console.WriteLine("value=" + i.ToString());
}
}
public static Func<int, int> Increment()
{
return delegate(int i) { return ++i; };
}
}