I have a question regarding method overlading given below
Fun1(int a);
Fun1(ref int a);
Is this method overloading? IF Yes then WHY and if No then WHY?
As per documentation:
Methods can be overloaded when one method has a ref or out parameter and the other has a value parameter
So the answer to your question is yes, but why?
As per definition of function overloading:
Function overloading (also called method overloading) is a programming concept that allows programmers to define two or more functions with the same name and in the same scope. Each function has a unique signature (or header), which is derived from:
function/procedure name
number of arguments
arguments' type
arguments' order
When you are passing a parameter without using the ref keyword you are actually passing a reference to the variable thus the type of argument is different from that when passed without ref keyword.
public void function(ref int abc)
{
Console.WriteLine("Result Ref: " + abc);
}
public void function(int abc)
{
Console.WriteLine("Result: " + abc);
}
Thus the signature of the above two functions is not the same as the type of argument passed to the both is not the same.
Hope I was able to satisfy you with my answer :).
Also I would like to add another point to the discussion that overloading is not possible in case of using out with one function and ref with another as in this case both the types are considered as same so no overloading in the following case:
public void function(ref int abc)
{
Console.WriteLine("Result Ref: " + abc);
}
public void function(out int abc)
{
abc = 1221;
Console.WriteLine("Result Out: " + abc);
}
1) Fun1(int a);
2) Fun1(ref int a);
1 and 2 are different functions. 1 - pass by value, 2 - pass by reference.
For example:
public static void Func(int i)
{
i++;
Console.WriteLine("int a = {0}", i);
}
public static void Func(ref int i)
{
i++;
Console.WriteLine("ref int a = {0}", i);
}
static void Main(string[] args)
{
int a = 9;
Func(ref a);
// Func(a);
Console.WriteLine("a = {0}", a);
Console.Read();
}
output:
ref int a = 10
a = 10
it means that a is passed by reference and function Func(ref int i) can change its value.
in second case when you call Func(a) in Main function result is:
int a = 10
a = 9
It means that a is passed by value.
You can implement both functions in one class․
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 *
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
Lets imagine simple delegate calls:
void Main()
{
Func<int, int, string> tfunc = null;
tfunc += Add; // bind first method
tfunc += Sub; // bind second method
Console.WriteLine(tfunc(2, 2));
}
private string Add(int a, int b)
{
return "Add: " + (a + b).ToString();
}
private string Sub(int a, int b)
{
return "Sub: " + (a - b).ToString();
}
The result of this program is:
Sub: 0
So, why Add method was not called? I'm expecting to call Method Add, and then method Sub.
Add was correctly chained and called, take a look at the result of
void Main()
{
Func<int, int, string> tfunc = null;
tfunc += Add; // bind first method
tfunc += Sub; // bind second method
Console.WriteLine(tfunc(2, 2));
}
private string Add(int a, int b)
{
Console.WriteLine("Inside Add");
return "Add: " + (a + b).ToString();
}
private string Sub(int a, int b)
{
Console.WriteLine("Inside Sub");
return "Sub: " + (a - b).ToString();
}
It is:
Inside Add
Inside Sub
Sub: 0
What is not chained, because there is no way to access it, is the result of the Add method. Delegates that return a value, in case of chaining, return the value of the last method invoked, that is the last method that was added to the delegate.
This is specified in part 15.4 of the C# 4.0 language specification
Invocation of a delegate instance whose invocation list contains
multiple entries proceeds by invoking each of the methods in the
invocation list, synchronously, in order. ...
If the delegate invocation includes output parameters or a
return value, their final value will come from the invocation of the
last delegate in the list.
The problem is that the return value is not passed between the method invocations, so the output only captures the last string returned. I.e. the return of Add is lost.
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; };
}
}