what does this use of delegate mean? - c#

I can't understand why delegate is used here:
List<string> temp_list = new List<string>();
string[] temp_array;
temp_array = Array.ConvertAll(arr_DL[m], delegate (int j) { return j.ToString(); });
temp_list.AddRange(temp_array.ToList());
the code is supposed to convert the array to list.
Can someone help explain the use of delegate here?

That because it's the second parameter of ConvertAll method. It represent how each element in initial Array should be converted:
A Converter<TInput, TOutput> that converts each element from one type to another type.
So your delegate sais "convert each int j to string by performing j.ToString();"

This part:
delegate (int j) { return j.ToString(); }
creates so-called "anonymous method" as second parameter TOutput, which used to convert int variable input into String then passes it into Array.ConvertAll() method. Anonymous methods used widely on C# 2.0, where in C# 3.0 they substituted with lambda expression like this:
delegate String output (int j);
String output = x => { x.ToString(); }
Reference: https://msdn.microsoft.com/en-us/library/bb882516.aspx
CMIIW.

Related

confused about return methods and voids in C#

Want feedback if i`m correct here?
Use void if you are not returning anything in a method,
otherwise
Name your data types used in the method criteria before method name.
use Return in the method before the calculation or output.
So something like this.
static int MyMethod(int x)
{
return 5 + x;
}
static void Main(string[] args)
{
Console.WriteLine(MyMethod(3));
}
// Outputs 8 (5 + 3)
What if my method has ints and doubles?
Do I write as follows? (another words do I have to mention every type i`m using prior to the method name?
static int double myMethod (int x, double y)
Even with that I dont know when is a method void? It seems my methods all return values.
Isnt the following returning the values of the arguments? So why should I label it void?
static void MyMethod(string fname, int age)
{
Console.WriteLine(fname + " is " + age);
}
static void Main(string[] args)
{
MyMethod("Liam", 20);
MyMethod("Jenny", 25);
MyMethod("Tom", 31);
}
I can only think that a void means there is no new calculation being done in the actual method body, passing arguments into a method and spitting them out for user viewing does not mean its "returning a value", I dont know what i`m talking about.
Let's be completely clear about what these bullets mean.
Use void if you are not returning anything in a method, otherwise
In this context, "return" means that the method provides an output that can be assigned to a variable by the caller. For example
int Return10()
{
return 10;
}
...allows the caller to do this:
int x = Return10();
Console.WriteLine(x); //Outputs "10"
A method should "return" void when its results cannot be assigned. For example, if the results are printed on the screen.
void Print10()
{
Console.WriteLine("10"); //Prints 10 to the screen
}
...which allows the caller to do this:
Print10();
You cannot assign it because it doesn't return anything. This doesn't work:
int x = Print10(); //Compiler error
Name your data types used in the method criteria before method name.
A method can return exactly one value or object. So "types" here is wrong. You can only specify one type.
Use return in the method before the calculation or output.
This is a little misleading. The return keyword should be followed by an expression which can be assigned.
int Return10()
{
return 10 + 10; //Is okay because it's an expression and could be assigned
}
int Return10()
{
var x = 10 + 10;
return x; //This is also okay; in fact it does exactly the same thing as the previous example
}
int Return10()
{
return Console.WriteLine("10"); //Compiler error; can't be assigned to anything.
}
By the way, a method can also output something and return it:
int WriteAndReturn10()
{
int x = 10;
Console.WriteLine(x);
return x;
}
I am going to address the following
What if my method has ints and doubles? Do I write as follows?
(another words do I have to mention every type i`m using prior to the
method name?
There are no built in ways or syntax to return more than one type from a method as the return parameter.. This is basically historical and has been this way since dinosaurs roamed the earth.
However, there are lots of options that achieve the same result. For instance, you could use a custom struct, you could use out parameters, you could use a class, or a delegate parameter of some kind. However, a modern succinct approach might be to use a Value Tuple:
static (int someInt, double someDouble) myMethod (int x, double y)
{
return (x,y);
}
Fun Fact : even though this looks like you a returning more than one type, you are actually just invoking a special syntax that wraps your return parameters in a single type of struct
Usage
var result = myMethod(1,2.2);
Console.WriteLine(result.someInt);
Console.WriteLine(result.someDouble);
Or if you want to get fancy, you can use the newer deconstructed syntax
var (someInt, someDouble) = myMethod(1,2.2);
Console.WriteLine(someInt);
Console.WriteLine(someDouble);
Additional Resources
return (C# Reference)
Methods (C# Programming Guide)
Tuple types (C# reference)
out parameter modifier (C# Reference)
ref (C# Reference)
Using Delegates (C# Programming Guide)

Is it possible to use a method argument as an array extension method

I am trying to pass an argument to a method, and then use that argument as a array extension method, but I am struggling. My code is:
//create method
public static void BankChoice(string SearchItem)
{
//declare variables
double tempMin = 0;
int minIndex = 0;
//set a temporary double as the first index of array
tempMin = Program.array_SH1[0].SearchItem;
//start loop to go through whole array
for (int y = 0; y <= array_SH1.Length; y++)
{
//if the temp double is bigger than the array item,
//make array item temp double
if (tempMin > array_SH1[y].SearchItem)
{
tempMin = array_SH1[y].SearchItem;
minIndex = y;
}
}
}
I would then call the code as:
BankChoice("OpenPrice")
However this doesn't work. The compiler won't accept the string as the array extension and it just throws and error.
Is there anyway to fix this without having to do it longhand, and create a method for all variations of SearchItem
Thanks
What you can do is to supply a delegate:
public static void BankChoice(Func<ArrayValueType, double> searchBy)
{
//...
// use the delegate to evaluate the result for each time you need to get the value from an item in your array.
tempMin = searchBy(Program.array_SH1[0]);
//...
}
Where ArrayValueType is the type of object in your array. Then you call it with
BankChoice(x => x.OpenPrice);
This will allow you to specify a property to search on, and it will be done in a type safe manner. The only restriction at the moment is that the property is convertible to a double. It's possible to get around that for properties of a generic type, and there are various ways to do that depending on what your needs are.

How to use F# to process lists from C#

I'm trying to figure out how to use an F# library from a C# assembly, I have used C# quite a bit, but have never used F#.
Here is the F# Class..
namespace FLib
type Class1() =
member this.square(x)=x*x
member this.doit(x, op) = List.map op (Seq.toList(x))|>List.toSeq
member this.squareAllDirect(x) = List.map this.square (Seq.toList(x))|>List.toSeq
member this.squareAllIndirect(x) = this.doit x, this.square
Here is the C# using it
class Program
{
static void Main(string[] args)
{
FLib.Class1 f = new FLib.Class1();
List<int> l=new List<int>(){1,2,3,4,5};
var q =f.squareAllDirect(l);
var r = f.squareIndirect(l);
foreach (int i in r)
Console.Write("{0},",i);
Console.ReadKey();
}
}
The squareAllDirect function works as expected... but the squareAllIndirect call from c# has an exception:
The Type argument for method 'FLib.Class1.squareAllIndirect (System.Tuple,Microsoft.FSharp.Core.FSharpFunc'2>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
It looks you are expecting your squareAllIndirect function to take and returns a int seq
However if you mouse over it you will see it takes and returns a int seq * (int -> int)
Tuple is lower precedence than function call so x is passed as both arguments to doit.
You need to surround the parameters of your function call in ().
member this.squareAllIndirect(x) = this.doit(x, this.square)
That will ensure you take and return what you expect.

Equivalent of func_get_arg in C#?

Is there an equivalent to func_get_arg (php) in C#?
func_get_arg ( int $arg_num ):
Gets the specified argument from a user-defined function's argument list.
This function may be used in conjunction with func_get_args() and func_num_args() to allow user-defined functions to accept variable-length argument lists.
It basically means the index can be used to get the argument value...
Thanks
C# is statically typed, so function signatures matter. You can't just call a method with any number of arguments, which really means there is no need for func_get_arg.
That said, you can get pretty close if you have a method such as this one:
void MyMethod(params object[] args)
{
var indexOfArgument = 42; // or whatever
var valueOfArgument = args[indexOfArgument]; // should also check array bounds
}
Of course if all your arguments are typed as System.Object there's not much you can do with them, but from a syntactic viewpoint it's close (plus, you could also have a method that accepts params T[] args for any type T).
in C# there's a method "__arglist()"
or you can easily make a function accept variable number of parameters like this
int Average(params int[] ints)
{
int total = 0;
foreach(int i in ints) // loop to the number of parameters
total += i;
return (ints.Length > 0 ? total / ints.Length : 0);
}
As I understand it, the purpose of func_get_arg in PHP is to have a variable number of arguments to a function. Here's the equivilent to that in C#:
public void Foo(string realArg, int anotherRealArg, params int[] variableArgs)
{
Console.WriteLine("My real string argument was " + realArg);
Console.WriteLine("My real integer argument was " + anotherRealArg);
Console.WriteLine("And I was given " + variableArgs.Length + " extra arguments");
}
// Usage
Foo("Bar", 1, 2, 3, 4, 5);
Within the method, variableArgs is a regular array. Before accessing it, you'll want to check its Length to be sure you don't get an IndexOutOfRangeException.

Strange behaviour with incrementing int when using Action<> delegate

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

Categories