Enumerator and function scopes - c#

Why an Enumerator does not keep track of the item in the same function but not if the MoveNext operation happens in other function ?
Example:
public static void Test()
{
var array = new List<Int32>(new Int32[] { 1, 2, 3, 4, 5 });
var e = array.GetEnumerator();
e.MoveNext();
e.MoveNext();
Console.WriteLine(e.Current); // 2
Incremenet(e);
Console.WriteLine(e.Current); //2
}
static void Incremenet(IEnumerator<Int32> e)
{
Console.WriteLine("Inside " + e.Current); //2
e.MoveNext();
Console.WriteLine("Inside " + e.Current); // 3
e.MoveNext();
Console.WriteLine("Inside " + e.Current); //4
}
I was expecting to get 5 in the last CW, but I get 2, like it was never incremented. Why the MoveNext inside the Increment function are forgotten when the function returns?
Cheers.

List<T>'s enumerator type List<T>.Enumerator is not a class, but a struct. Since GetEnumerator exposes that the return type is List<T>.Enumerator, when you use var, e's type is List<T>.Enumerator, so when you pass it to Incremenet, it is automatically boxed to be an IEnumerator<Int32> object. This is the cause of the strange behavior you're seeing.
If you type e as an IEnumerator<Int32>, the boxing happens as soon as you get the object, so this strange behavior does not happen: it works the same whether you run the other code in Test or in Increment (I fixed the spelling on that method, by the way, it's not "Incremenet").
public static void Test()
{
var array = new List<Int32> { 1, 2, 3, 4, 5 };
IEnumerator<Int32> e = array.GetEnumerator(); // boxed here
e.MoveNext();
e.MoveNext();
Console.WriteLine(e.Current); // 2
Increment(e);
Console.WriteLine(e.Current); // now it's 4
}
static void Increment(IEnumerator<Int32> e)
{
Console.WriteLine("Inside " + e.Current); // 2
e.MoveNext();
Console.WriteLine("Inside " + e.Current); // 3
e.MoveNext();
Console.WriteLine("Inside " + e.Current); // 4
}
It is exposed as its type instead of IEnumerator<T> for performance reasons. foreach is smart enough to call MoveNext and Current without boxing or virtual dispatch in such a case, and handles value type semantics without a problem. It does cause confusion, as you've seen, when you don't take great care of how you handle it though, since mutable structs are evil.

For the same reason test is 1 after increment in the following test case. This is normal behavior for a value type.
static void Main(string[] args)
{
int test = 1;
Increment(test);
Console.WriteLine("After increment: " + test);
}
static void Increment(int test)//add ref and the original variable will also update
{
test += 1;
Console.WriteLine(test);
}
As Servy pointed out technically, the example does differ in that the local variable test is immutable. In reality the behavior we see is because the variable is copied to the Increment method. However, my point is that this type of behavior is consistent across value types (both properties and local variables). For further evidence of this fact:
struct MutableStruct
{
public int EvilInt { get; set; }
}
class Program
{
static void Main(string[] args)
{
var testStruct = new MutableStruct();
testStruct.EvilInt = 1;
int test = 1;
Increment(test, testStruct);
Console.WriteLine("After increment: " + test + " and..." + testStruct.EvilInt);//both 1
}
static void Increment(int test, MutableStruct test2)
{
test2.EvilInt += 1;
test += 1;
Console.WriteLine(test + " and..." + test2.EvilInt);//both 2
}
}
As we can see here this behavior is normal across value types. In both the case of local immutable value types and mutable structs the behavior remains consistent.

Related

Call function with a parameter from another function

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();
}
}
}
}

Can ref and Out keyword can decide method overloading

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․

Why output is 5? [duplicate]

This question already has answers here:
Multicast delegate of type Func (with return value)?
(3 answers)
Closed 5 years ago.
I am trying to add 2 more functions to my delegate but it seems it doesn't process the functions I added. Following program outputs 5. I expect 10. Why is this the case?
using System;
namespace abc
{
public delegate int Del(int k);
class Class1
{
public int Add2(int value)
{
return value = value + 2;
}
public int Add3(int value)
{
return value = value + 3;
}
}
class Program
{
static void Main(string[] args)
{
Class1 c = new Class1();
Del mydel = c.Add2;
mydel += c.Add3;
mydel += c.Add2;
Console.WriteLine(mydel(3));
Console.ReadLine();
}
}
}
What happens when you call mydel(3) is this:
Add2(3) is called. This returns 3 + 2 = 5, the return value of which is discarded.
Add3(3) is called. This returns 3 + 3 = 6, the return value of
which is discarded.
Add2(3) is called. This returns 3 + 2 = 5, the return value of which is printed.
When you chain delegates, the return value of one is NOT passed as a parameter to a chained one.
Note that the delegates are called in LIFO order.
If you want to see how to actually chain functions together using delegates, see this thread.
Alternatively, as per the linked answer (and as mentioned by Toskr in the comments below), you can use GetInvocationList() and DynamicInvoke() to chain the methods together, but this is a very unusual thing to do:
static void Main()
{
Class1 c = new Class1();
Del mydel = c.Add2;
mydel += c.Add3;
mydel += c.Add2;
int result = 3;
foreach (var func in mydel.GetInvocationList())
{
result = (int)func.DynamicInvoke(result);
}
Console.WriteLine(result);
}

C# - Delegate with any amount of custom parameters [duplicate]

This question already has answers here:
How can I design a class to receive a delegate having an unknown number of parameters?
(6 answers)
C# How to call a method with unknown number of parameters
(3 answers)
Closed 5 years ago.
I want a delegate that I can store in a variable for later use that has custom amounts of custom parameters. What I mean by that, is that I want to pus it different methods with different return types and different arguments. For example:
public double Sum (double a, double b) {return a + b;}
public char GetFirst (string a) {return a[0];}
public bool canFlipTable (object[] thingsOnIt) {return thingsOnIt.Length <= 3;}
DoTheThing<double> thing1 = new DoTheThing<double>(Sum);
DoTheThing<char> thing2 = new DoTheThing<char>(GetFirst);
DoTheThing<bool> thing3 = new DoTheThing<bool>(canFlipTable);
thing1.Call(10.3, 5.6); //15.9
thing2.Call("Hello World"); //'H'
thing3.Call(new object[] {new Lamp(), new Laptop(), new CoffeMug()}); //true
I figured out the return value and the call method already, but I'm having a problem with storing the methods
If I use "public DoTheThing(Action method)" it says, that the arguments doesn't match
I even tried with a delegate that had "params object[] p" as arguments, but it didn't work either
EDIT:
I forgot to tell, the method WILL always have a return type and at least 1 parameter
EDIT 2:
My goal is creating a wrapper class, that caches outputs from very expensive methods and if the same thing gets called again, it returns the cached value.
Of course I could solve this with an interface, but I want to do this with classes that I can't simply edit and I want to make this felxible too, so having the cache at the same place where I call the method is not an option either.
My code sofar:
public class DoTheThing <T>
{
public delegate T Method(params object[] parameters);
Func<T> method;
ParameterInfo[] pInfo;
public DoTheThing (Method method)
{
this.method = method;
Type type = typeof(Method);
MethodInfo info = type.GetMethod ("Invoke");
if (info.ReturnType != typeof(T)) {
throw new Exception ("Type of DoTheThing and method don't match");
}
pInfo = info.GetParameters ();
}
public T Call (params object[] parameters) {
if (parameters.Length != pInfo.Length) {
throw new Exception ("Wrong number of arguments, " + parameters.Length + " instead of " + pInfo.Length);
return default(T);
}
for (int i = 0; i < parameters.Length; i++) {
if (pInfo[i].ParameterType != parameters[i].GetType()) {
throw new Exception ("Wrong parameter: " + parameters [i].GetType () + " instead of " + pInfo [i].ParameterType + " at position: " + i);
return default(T);
}
}
return (T)method.DynamicInvoke (parameters);
}
}
Before trying to figure how to do it, I would really question the problem that leads me to have such a kind of delegate. I would bet if I knew the context better, there would be a solution that would eliminate your requirement.
Having that said, delegates are classes that inherit from MulticastDelegate. In fact, when you declare a delegate, you are creating a new class type with MulticastDelegate as its base class. That means the following code works:
public static double Sum(double a, double b)
{
return a + b;
}
public static string SayHello()
{
return "Hello";
}
static void Main(string[] args)
{
MulticastDelegate mydel = new Func<double, double, double>(Sum);
var ret = mydel.DynamicInvoke(1, 2);
System.Console.WriteLine(ret);
mydel = new Func<string>(SayHello);
ret = mydel.DynamicInvoke();
System.Console.WriteLine(ret);
mydel = new Func<string, int, string> ((s, i) => {
return $"Would be {s}, {i} times";
});
ret = mydel.DynamicInvoke("Hello", 5);
System.Console.WriteLine(ret);
}
Because "mydel" variable is of the base class type (MulticastDelegate), we can actually use it with any kind of delegate and invoke it with arbitrary parameters. If they don't match the method being invoked, it will throw at runtime.

Passing by value?

I am having an issue with C# function argument passing.
I was wondering how would I make a C# function accept a parameter by value (to make a copy of the original object).
I thought that was the default way C# handled these things, but in the following code:
using System;
using System.Collections.Generic;
using System.Linq;
class MaximumElement
{
static void Main(string[] args)
{
Stack<int> numbers = new Stack<int>();
int n = int.Parse(Console.ReadLine());
for (int i = 0; i < n; i++)
{
string input = Console.ReadLine();
switch (input)
{
case "2": numbers.Pop(); break;
case "3": Console.WriteLine(maxElement(numbers)); break;
default:
string[] argz = input.Split(' ');
numbers.Push(int.Parse(argz[1]));
break;
}
}
}
public static int maxElement(Stack<int> stack)
{
int max = stack.Peek();
for (int i = 0; i < stack.Count; i++)
{
if (max >= stack.Peek())
{
stack.Pop();
}
else if (max < stack.Peek())
{
max = stack.Pop();
}
}
return max;
}
}
My maxElement() function actually changes the original stack I pass to it, and the only way to get around it is to manually make a copy of the stack I pass to the function inside the function.
Thanks for any responses in advance :)
Don't mix passing arguments by value or reference with value types and reference types. Its a common beginner's mistake and you need to have a clear understanding of how both things, allthough related in some way, are completely different features of the language.
I'll probably not use precise terminology because english is not my language but I hope I can get the idea across:
Value type: The variable is the value itself. When you write the following: int i = 1; the variable i holds the value 1.
Reference type: The variable is a reference that points to a place in memory where the object is. That means that, when you say string s = "Hello"; s does not contain "Hello", it contains the memory address where "Hello" is stored.
So what happens when you pass an argument by value (default in C#). We have two possibilities:
Argument is a value type: You get a copy of the variable, that means
that if you pass along i = 1 you recieve a copy which also
contains 1, but both are alltogether different objects.
This is obvious when dealing with mutable value types, for example System.Drawing.Point:
Point point = new Point(0, 0);
Frob(point);
var b = point.X == 1 && point.Y == 1; //False, point does not change.
void Frob(Point p) { p.Offset(1, 1); } // p is a copy of point and therefore contains a copy of the value stored in point, not the value itself.
Argument is a reference type: You get a copy of the variable, that means you get a copy of the reference to the memory address, but the object the copy is pointing at is the same. This is the scenario you are in.
Foo foo = new Foo();
foo.Blah = 1;
Frob(foo);
var b = foo.Blah == 2; //True, foo.Blah has been modified.
void Frob(Foo f) { foo.Blah = 2; } //both foo and f point to the same object.
Notice that in both cases what you can't do is modify what the reference is pointing to. This won't work:
string s = "hello";
foo(s);
var b = s == "bye"; //false, s still points to the original string
void Foo(string str)
{
str = "bye";
}
Now, what happens if we pass by reference? Well, the main difference is that you are passing the variable itself, not a copy. That means that in case of a value type you are passing the original value and in case of a reference type, the original address, not a copy. This allows the following:
//Value type
Point point = new Point(0, 0);
Frob(ref point);
var b = point.X == 1 && point.Y == 1; //True, point and p are the same variable.
void Frob(ref Point p) { p.Offset(1, 1); }
and
//Value or reference type
string s = "hello";
foo(ref s);
var b = s == "bye"; //true
void Foo(ref string str)
{
str = "bye";
}
Hope this clarifies the difference.
It is a little complex. From MSDN (https://msdn.microsoft.com/en-us/library/s6938f28.aspx):
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 pointed to by the reference, such as the value of a class member. However, you cannot change the value of the reference itself; that is, you cannot use the same reference to allocate memory for a new class and have it persist outside the block. To do that, pass the parameter using the ref or out keyword. For simplicity, the following examples use ref.
Here is the code example they provide:
static void Change(int[] pArray)
{
pArray[0] = 888; // This change affects the original element.
pArray = new int[5] {-3, -1, -2, -3, -4}; // This change is local.
Now, if you use the ref keyword on your parameter
static void Change(ref int[] pArray)
{
pArray[0] = 888; // This change affects the original element.
pArray = new int[5] {-3, -1, -2, -3, -4}; // This change also affects the original
So, with those things in mind, you could...
public static int maxElement(Stack<int> stack)
{
stack = new Stack<int>(stack); // Now changes will be local
int max = stack.Peek();
for (int i = 0; i < stack.Count; i++)
{
if (max >= stack.Peek())
{
stack.Pop();
}
else if (max < stack.Peek())
{
max = stack.Pop();
}
}
return max;
}
You would need to make a copy of the Stack, which if a shallow copy works you can use Clone() method.

Categories