Here i have three functions; passing a reference from function 1 to function 2.So in function 2, a is a reference. Then why it is not allowed to pass this same reference to function 3? without using the keyword ref
Function 1:
public void funReadA()
{
double a=10;
//read value for a
funReadB(ref a);
}
Function 2 :
public void funReadB(ref double a)
{
double b = 25;
a = 11;
// sum(a, b);this method call is not allowed
sum(ref a, b);// why ref a is required? a is already a reference na?
}
Function 3:
public double sum(ref double a,double b)
{
return a += b;
}
The ref keyword on the call site is required mostly to make sure the person who wrote the calling code is aware that he is passing a reference, and so that the value could change.
It's not strictly necessary from a programming language point of view, but it's a good idea from a programmer point of view.
Related
I have a function that repeatedly calls another function.
The second function has a bool parameter that changes the way it behaves, so when I call the first function I want to have a parameter that specifies the way the second function behaves.
void Function1(int n, bool differentBehavior = false)
{
int a = Function2(n, differentBehavior);
int b = Function2(1, differentBehavior);
int c = Function2(2, differentBehavior);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
The code itself is obviously an example (in reality the second function is called over 20 times and for code readability I would love to not have to specify the second parameter every time), but I put it there to explain what I'm currently doing. Is there no better way to achieve this?
You can introduce a local function to capture the second argument like so:
int Function1(int n, bool differentBehavior = false)
{
int func(int n) => Function2(n, differentBehavior);
int a = func(n);
int b = func(1);
int c = func(2);
return a + b + c;
}
This is called "partial function application". See more here:
https://codeblog.jonskeet.uk/2012/01/30/currying-vs-partial-function-application/
While C# doesn't support true function Currying nor first-class partial function application, you can always
use a new locally scoped function (aka a local function) to wrap your Function2 with predefined arguments... which is conceptually almost the same thing as partial application, just without referential-transparency, and awkward delegate types.
Anyway, if you want to pass the outer Function1's differentBehavior argument value to Function2 then you will need to use a closure, which will capture the variable, but this will introduce slight runtime performance complications: as a closure generally means a GC heap allocation and copying function local state from the stack onto the heap and yada yada.
However, if you're only using constant parameter values - or you're okay with using different wrappers for different predefined argument values, then you can use a static local function (requires C# 8.0 or later) which prevents you from unintentionally creating a closure.
For example:
void Function1(int n, bool differentBehavior = false)
{
// Look ma, no closure!
static int PartiallyAppliedFunc2_False(int x) => Function2( x: x, differentBehavior: false );
static int PartiallyAppliedFunc2_True(int x) => Function2( x: x, differentBehavior: true );
int a = PartiallyAppliedFunc2_False(n);
int b = PartiallyAppliedFunc2_False(1);
int c = PartiallyAppliedFunc2_True(2);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
One thing to look at when a lot of parameters are being passed on the stack is whether there is some higher-level state that could be represented by a member variable of the class.
Here's some code for the most basic kind of state machine. This general approach might help solve the problem you're having:
class Program
{
enum Behaviors
{
BehaviorA,
BehaviorB,
BehaviorC,
}
static Behaviors State { get; set; }
static void Main(string[] args)
{
for (State = Behaviors.BehaviorA; State <= Behaviors.BehaviorC; State++)
{
Console.WriteLine($"Function returned { Function1(0)}");
}
int Function1(int n)
{
int a = Function2(n);
int b = Function2(1);
int c = Function2(2);
return a + b + c;
}
int Function2(int x)
{
switch (State)
{
case Behaviors.BehaviorA:
return x * 10;
case Behaviors.BehaviorB:
return x * 20;
case Behaviors.BehaviorC:
return x * 30;
default:
throw new NotImplementedException();
}
}
}
}
I am trying to read some code on the internet, but still cannot figure it out.
The code is:
private delegate string GetAString();
static void Main()
{
int x = 40;
GetAString firstStringMethod = new GetAString(x.ToString);
Console.WriteLine(firstStringMethod());
}
My question is "delegate string GetAString()" does not need parameters, but when it is instantiated, it has the x.ToString parameter.
Why? Can anyone explain this?
Thanks.
A delegate is a special type of variable that can hold a reference to a method (not the result of the method but the method itself), allowing it to be passed around and invoked in places where you perhaps don't have access to the object the method belongs to.
From the docs:
Represents a delegate, which is a data structure that refers to a static method or to a class instance and an instance method of that class.
Your code:
GetAString firstStringMethod = new GetAString(x.ToString);
Note the lack of () at the end of x.ToString. We're not calling x.ToString() here. We're creating a GetAString and passing x.ToString (which is a method that satisfies the signature required by the delegate).
This means that when we call firstStringMethod() it will call x.ToString() and proxy the result to you.
Consider another example:
public delegate int Operation(int a, int b);
We could define multiple methods:
public int Sum(int a, int b)
{
return a + b;
}
public int Multiply(int a, int b)
{
return a * b;
}
And then switch according to user input:
Operation o;
switch (Console.ReadLine())
{
case "+":
o = new Operation(Sum);
break;
case "*":
o = new Operation(Multiply);
break;
default:
Console.WriteLine("invalid operation");
return;
}
Console.WriteLine(o(4, 3));
If the user inputs "+" then the result will be 7, while inputting "*" will result in "12".
You can see from this example that we're not passing the arguments of Sum or Multiply when we instantiate o. We're simply passing the method. We then use the delegate to supply the arguments and get the result.
Example if user input is +
Example if user input is *
This question already has answers here:
What is the difference between 2 methods with ref object par and without?
(5 answers)
Closed 8 years ago.
I have been reading a bit the tutorials on MSDN to get my head around pass-by-reference in C#, ref and out and I came across the following code sample:
using System;
class TheClass
{
public int x;
}
struct TheStruct
{
public int x;
}
class TestClass
{
public static void structtaker(TheStruct s)
{
s.x = 5;
}
public static void classtaker(TheClass c)
{
c.x = 5;
}
public static void Main()
{
TheStruct a = new TheStruct();
TheClass b = new TheClass();
a.x = 1;
b.x = 1;
structtaker(a);
classtaker(b);
Console.WriteLine("a.x = {0}", a.x); //prints 1
Console.WriteLine("b.x = {0}", b.x); //prints 5
}
}
The note to this from the tutorial:
This example shows that when a struct is passed to a method, a copy of
the struct is passed, but when a class instance is passed, a reference
is passed.
I totally understood it, but my question is, if a reference is passed in C# to the parameter, why would they need ref as in the following sample:
void tearDown(ref myClass a)
{
a = null;
}
MyClass b = new MyClass();
this.tearDown(ref b);
assert(b == null);
//b is null
??? I thought C# was the same in C - pass-by-value.
In C#, basically all classes as pointers. However, passing by ref/out or not is like passing the pointer to a pointer or the pointer itself.
When you pass a class (as per the first sample) any changes to the classes members are carried over. However, changing the reference to the object itself would not yield the results. Say you replace
public static void classtaker(TheClass c)
{
c.x = 5;
}
With
public static void classtaker(TheClass c)
{
c = new TheClass();
c.x = 5;
}
Since c is not an out or ref paramter, you're reassigning the local pointer to c, not the value of c itself. Since you only modified the .x of the local c, the result would be that b.x == 1 after calling this modified ClassTaker.
Now, as per your second example, since a is a ref parameter, changes to the value a itself will be seen in the calling scope, as in the example, but removing the ref from the call would cause the null assertion to fail.
Basically, ref passing passes what can be thought of as a pointer to your pointer, while calling without ref/out passes a copied pointer to your object data.
EDIT:
The reason one can assign c.X in method scope is because the object c points to the object X, and you'll always get the same pointer to X regardless of the ref/out parameter or not. Instead, ref/out modifies your ability to change the value c as seen by the calling scope.
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; };
}
}