Union of delegates [duplicate] - c#

I have this code:
public void myMethod()
{
int a = 10;
int b = 20;
Func<int, int, int> multiplyDelegate;
multiplyDelegate = Multiply;
multiplyDelegate += Multiply2;
Console.WriteLine(multiplyDelegate(a,b));
}
public int Multiply(int x, int y)
{
return x * y;
}
public int Multiply2(int x, int y)
{
return x * y + 10;
}
By running myMethod, I expect the console to show the returns from both methods "Multiply" and "Multiply2" but only the return from the method "Multiply2" is shown. Have I done something wrong here or have I misunderstood the concept of delegates? From what I've learned a delegate is an array of references to methods.

From Using Delegates (C# Programming Guide):
If the delegate has a return value and/or out parameters, it returns
the return value and parameters of the last method invoked.

You are right delegate can store methods and invoke multiple methods at once. It will return the last one except if you explicitly Invoke them.
Using your code, here is an example of explicite Invoke for all of your collection of methods.
var results = multiplyDelegate.GetInvocationList().Select(x => (int)x.DynamicInvoke(10, 20));
foreach (var result in results)
Console.WriteLine(result);
EDIT :
This will work for function Func and not Action. Here is an example supposing it's an Action
foreach (Delegate action in multiplyDelegate.GetInvocationList())
{
action.DynamicInvoke(10, 20);
// Do Something
}
This second example work for Func as well.

I don't have any official sources for this, but I think what is happening is that you can't return two values from one delegate call. Therefore, the last value returned is used.
Although only the last return value is used, the two methods are indeed executed. We can prove this by printing some stuff before we return:
public int Multiply(int x, int y)
{
Console.WriteLine("Hello1");
return x * y;
}
public int Multiply2(int x, int y)
{
Console.WriteLine("Hello2");
return x * y + 10;
}
Both Hello1 and Hello2 are printed.

Only one object can be returned and since Multiple2 is the last to execute it get's outputted in the console.
There isnt a way to change that.
You could do:
public void myMethod()
{
int a = 10;
int b = 20;
Action<int, int> multiplyDelegate;
multiplyDelegate = Multiply;
multiplyDelegate += Multiply2;
multiplyDelegate(10, 20);
Console.Read();
}
public void Multiply(int x, int y)
{
Console.WriteLine(x * 2);
}
public void Multiply2(int x, int y)
{
Console.WriteLine(x * y + 10);
}

I had this question too and test several things like another way of setting method to the delegate but finally only usable way is to write another line after each set:
public void myMethod()
{
int a = 10;
int b = 20;
Func<int, int, int> multiplyDelegate;
multiplyDelegate = Multiply;
Console.WriteLine(multiplyDelegate(a,b));
multiplyDelegate += Multiply2;
Console.WriteLine(multiplyDelegate(a,b));
}
public int Multiply(int x, int y)
{
return x * y;
}
public int Multiply2(int x, int y)
{
return x * y + 10;
}

Related

Overloading methods for different geomethrical figures areas

I need to overload a method for it to be able to calculate the area of a circle, square, rectangle, triangle and a trapezoid. I think I've got them all figured out but the circle seems to be a problem.
static void Pole(int x, double y = 3.14)
{
Console.WriteLine(x * x * y);
}
static int Pole(int x)
{
return x * x;
}
static int Pole(int x, int y)
{
return x * y;
}
static int Pole(int x, int y, int z = 2)
{
return x * y / z;
}
static int Pole(int x, int y, int v, int z = 2)
{
return (x + y) / z * v;
}
static void Main(string[] args)
{
int x = 2;
int y = 3.14;
Console.WriteLine(Pole(x, y));
Console.ReadKey();
I don't know what problem you're getting, but I can probably guess it's one of the following:
1) You're getting an error because one of your overload methods is returning void while the others are returning int (they all have to be the same)
or
2) What your Main method is calling is this method static int Pole(int x, int y) and not static void Pole(int x, double y = 3.14), which I'm assuming is the "Circle"; because you're passing in two ints instead of one int and one double.
Have you tried changing int to double for y in your Main method?
static void Main(string[] args)
{
int x = 2;
double y = 3.14;
Console.WriteLine(Pole(x, y));
Console.ReadKey();
}
also why dont you just pass in one parameter and have it multiply by 3.14 for the Pole overload method that's tasked with calculating the circle?
/// <summary>
/// Method to calculate a circle
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
static double Pole(int x)
{
return 3.14(x * x);
}
static void Main(string[] args)
{
int x = 2;
Console.WriteLine(Pole(x));
Console.ReadKey();
}
Another tip: add some notes in your code. You have 5 methods named Pole, one accepting one more int parameter than the last one and each of the 5 methods are calculating for a different shape.
Adding a summary to each method or just a simple comment will help you and anyone else trying to read your code, moving forward.
Important: Because these are overloads, you're going to need to change all your methods to return double instead of int just for the sake of the "Circle" Pole method. Having it as the only void method was probably causing the error for you to begin with.
This should be enough to get you started:
//Circle
static double Pole(int x, double y)
{
if(y != 3.14)
y = 3.14;
return y(x * x);
}
//Square
static double Pole(int x)
{
return x * x;
}
//Rectangle
static double Pole(int x, int y)
{
return x * y;
}
//Triangle
static double Pole(int x, int y, int z)
{
if(z != 2)
z = 2;
return x * y / z;
}
//Trapezoid
static double Pole(int x, int y, int v, int z)
{
if(z != 2)
z = 2;
return (x + y) / z * v;
}
static void Main(string[] args)
{
int x = 2;
double y = 3.14;
Console.WriteLine(Pole(x, y));
Console.ReadKey();
}

change variable declared in out scope or access it

I do not want to declare x variable but I wanna increment out y. Is it possible? Albahari code. The problem is y=1 is always initializing. I want to check if y exists then y = y + 1; and y = 0 otherwise. wanna access and increment variable created via out not by me.
using System;
namespace ConsoleAppX
{
class D
{
static void Foo(out int y)
{
y = 1;
y = y + 1; // Mutate y
}
// static int x;
static void Main(string[] args)
{
Foo(out int x);
Foo(out x);
Foo(out x);
Console.WriteLine(x);
Console.ReadLine();
}
}
}
Dont know what you are trying do :)
But Out method required Parameter to assign some value.
If you dont want assign any value and Just Manipulate the passed value
You can use ref
So your code may look like,
using System;
namespace ConsoleAppX
{
class D
{
static void Foo(ref int y)
{
//y = 1;
y = y + 1; // Mutate y
}
// static int x;
static void Main(string[] args)
{
int x = 0;
Foo(ref x);
Foo(ref x);
Foo(ref x);
Console.WriteLine(x);
Console.ReadLine();
}
}
}

C# delegate only writes out last method

I have this code:
public void myMethod()
{
int a = 10;
int b = 20;
Func<int, int, int> multiplyDelegate;
multiplyDelegate = Multiply;
multiplyDelegate += Multiply2;
Console.WriteLine(multiplyDelegate(a,b));
}
public int Multiply(int x, int y)
{
return x * y;
}
public int Multiply2(int x, int y)
{
return x * y + 10;
}
By running myMethod, I expect the console to show the returns from both methods "Multiply" and "Multiply2" but only the return from the method "Multiply2" is shown. Have I done something wrong here or have I misunderstood the concept of delegates? From what I've learned a delegate is an array of references to methods.
From Using Delegates (C# Programming Guide):
If the delegate has a return value and/or out parameters, it returns
the return value and parameters of the last method invoked.
You are right delegate can store methods and invoke multiple methods at once. It will return the last one except if you explicitly Invoke them.
Using your code, here is an example of explicite Invoke for all of your collection of methods.
var results = multiplyDelegate.GetInvocationList().Select(x => (int)x.DynamicInvoke(10, 20));
foreach (var result in results)
Console.WriteLine(result);
EDIT :
This will work for function Func and not Action. Here is an example supposing it's an Action
foreach (Delegate action in multiplyDelegate.GetInvocationList())
{
action.DynamicInvoke(10, 20);
// Do Something
}
This second example work for Func as well.
I don't have any official sources for this, but I think what is happening is that you can't return two values from one delegate call. Therefore, the last value returned is used.
Although only the last return value is used, the two methods are indeed executed. We can prove this by printing some stuff before we return:
public int Multiply(int x, int y)
{
Console.WriteLine("Hello1");
return x * y;
}
public int Multiply2(int x, int y)
{
Console.WriteLine("Hello2");
return x * y + 10;
}
Both Hello1 and Hello2 are printed.
Only one object can be returned and since Multiple2 is the last to execute it get's outputted in the console.
There isnt a way to change that.
You could do:
public void myMethod()
{
int a = 10;
int b = 20;
Action<int, int> multiplyDelegate;
multiplyDelegate = Multiply;
multiplyDelegate += Multiply2;
multiplyDelegate(10, 20);
Console.Read();
}
public void Multiply(int x, int y)
{
Console.WriteLine(x * 2);
}
public void Multiply2(int x, int y)
{
Console.WriteLine(x * y + 10);
}
I had this question too and test several things like another way of setting method to the delegate but finally only usable way is to write another line after each set:
public void myMethod()
{
int a = 10;
int b = 20;
Func<int, int, int> multiplyDelegate;
multiplyDelegate = Multiply;
Console.WriteLine(multiplyDelegate(a,b));
multiplyDelegate += Multiply2;
Console.WriteLine(multiplyDelegate(a,b));
}
public int Multiply(int x, int y)
{
return x * y;
}
public int Multiply2(int x, int y)
{
return x * y + 10;
}

Two Same variable declared in C#

I found a code online which i'm using in my Program, but to my surprise i found out there was a variable/function declared twice...
Now, If i'm to send any value to the DLL, which of the two would i send info to?
One use out, while the second does not...
See Code:
[DllImport("msman.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi, ExactSpelling=false)]
public static extern bool receive(int ID, double[] Bid, double[] Ask);
public bool receive(int ID, out double first, out double second)
{
bool flag;
double[] Array1st = new double[1];
double[] Array2nd = new double[1];
if (Form1.receive(ID, Array1st, Array2nd))
{
first = Array2nd[0];
second = Array1st[0];
flag = true;
}
else
{
second = 0;
first = 0;
flag = false;
}
return flag;
}
And, why is it possible to declare two variables..
My C# isn't great, but this looks like a standard case of method overloading.
Note the signature for each method
A: public static extern bool receive(int ID, double[] Bid, double[] Ask);
B: public bool receive(int ID, out double first, out double second)
A takes the following parameters: int, double[], double[]
while B takes int, double, double. Note the difference in types. So when you call it, the compiler says "oh, you want to call receive with an int and two double arrays. Got it, here you go!" and serves up A
Example of how the call works:
int x = 1; double y = 1.0; double z = 2.0;
receive(x, y, z); // <-- this calls the second method (B).
int x = 1; double[] y = new double[1]; double[]z = new double[1];
y[0] = 1.0;
z[0] = 1.0;
receive(x, y, z); // <-- this calls the first method (A)
Methods can be overloaded, that is, they can have the same name as long as the parameters differ (overloading on return type only is not allowed).
Hence this is valid:
void Foo(int x) { }
void Foo(char x) { }
Or, in your case:
bool receive(int ID, double[] Bid, double[] Ask);
bool receive(int ID, out double first, out double second)
Note that this is a standard language feature in many other languages, including C++.
Method overloading is object oriented concept where method can have same name and only parameters(signiture of method) are different.
using System;
class Test
{
static void receive(int x, double y)
{
Console.WriteLine("receive(int x, double y)");
}
static void receive(double x, int y)
{
Console.WriteLine("receive(double x, int y)");
}
static void Main()
{
receive(5, 10.2);
}
}
See here https://msdn.microsoft.com/en-us/library/aa691131(v=vs.71).aspx

Nullable generic object collection

public class CubicMatrix<Object?>
{
private int width;
private int height;
private int depth;
private Object[, ,] matrix;
public CubicMatrix(int inWidth, int inHeight, int inDepth)
{
width = inWidth;
height = inHeight;
depth = inDepth;
matrix = new Object[inWidth, inHeight, inDepth];
}
public void Add(Object toAdd, int x, int y, int z)
{
matrix[x, y, z] = toAdd;
}
public void Remove(int x, int y, int z)
{
matrix[x, y, z] = null;
}
public void Remove(Object toRemove)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
for (int z = 0; z < depth; z++)
{
Object value = matrix[x, y, z];
bool match = value.Equals(toRemove);
if (match == false)
{
continue;
}
matrix[x, y, z] = null;
}
}
}
}
public IEnumerable<Object> Values
{
get
{
LinkedList<Object> allValues = new LinkedList<Object>();
foreach (Object entry in matrix)
{
allValues.AddLast(entry);
}
return allValues.AsEnumerable<Object>();
}
}
public Object this[int x, int y, int z]
{
get
{
return matrix[x, y, z];
}
}
public IEnumerable<Object> RangeInclusive(int x1, int x2, int y1, int y2, int z1, int z2)
{
LinkedList<Object> list = new LinkedList<object>();
for (int a = x1; a <= x2; a++)
{
for (int b = y1; b <= y2; b++)
{
for (int c = z1; c <= z2; c++)
{
Object toAdd = matrix[a, b, c];
list.AddLast(toAdd);
}
}
}
return list.AsEnumerable<Object>();
}
public bool Available(int x, int y, int z)
{
Object toCheck = matrix[x, y, z];
if (toCheck != null)
{
return false;
}
return true;
}
}
I've created a Cubic Matrix class in C# to store items in 3 dimensions. I need to be able to add and remove items which is why I'm using Object? (I've been led to understand that you can't use nullable generics ie. T?). However this approach gnerates an error
Type parameter declaration must be an identifier not a type
If i don't use Object? though and just use Object or T i get this error instead
Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
What's the correct syntax and approach to use in this case?
If you want to restrict your generic type to objects only - i.e. no structs or simple types - you can add the where clause
public class CubicMatrix<T> where T : class
These means that T can only be a class.
When returning default(T) instead (as the error you are getting suggests), reference types will return null, numeric types will return 0, your custom classes will return null and nullables will return System.Nullable<T>. More about this in default Keyword in Generic Code (C# Programming Guide)
on MSDN.
I think you want to use the generic parameter T. You're making a simple container class, so allowing any generic parameter makes sense, whether it's nullable or not. To fix the error, just do what it says and use default(T) instead of null.
The error is because T could be a class or a struct, and structs can't be null. Therefore assigning a variable with type T to null is invalid. default(T) is null when T is a class and default values when T is a struct.

Categories

Resources