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);
}
Related
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․
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.
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.
I have an Object which contains several methods and outside of it I have a list of strings where each of the strings value is the name of the Method. I would like to Execute the the method based on the name. From expirience, in python it is deadly simple. In c# I assume that it should be done with delegates I suposse. Or with methodInvoking?
I wanted to ignore reflection on this one.
i python you can store methods as objects, because it is an object.
def a():
return 1
def b():
return 2
def c():
return 3
l= [a,b,c]
for i in l:
print i()
The output would be:
>>> 1
>>> 2
>>> 3
If you want to ignore reflection, you can create a delegate for each method call and store in a Dictionary.
Heres how you do it:
var methods = new Dictionary<string, Action >() {
{"Foo", () => Foo()},
{"Moo", () => Moo()},
{"Boo", () => Boo()}
};
methods["Foo"].Invoke();
Note that in your Python example, you are not "[executing] a method based on a string which contains its name" but rather adding the method to a collection.
You can do basically the same thing as you are doing in Python in C#. Take a look at the Func delegate.
class FuncExample
{
static void Main(string[] args)
{
var funcs = new List<Func<int>> { a, b, c };
foreach (var f in funcs)
{
Console.WriteLine(f());
}
}
private static int a()
{
return 1;
}
private static int b()
{
return 2;
}
private static int c()
{
return 3;
}
}
and the output is
1
2
3
If you need to execute a function based on its name as a string, Uri-Abramson's answer to this very question is a good place to start, though you may want to reconsider not using reflection.
This question already has answers here:
Calling a function from a string in C#
(5 answers)
Closed 1 year ago.
I have a method:
add(int x,int y)
I also have:
int a = 5;
int b = 6;
string s = "add";
Is it possible to call add(a,b) using the string s?
how can i do this in c#?
Using reflection.
add has to be a member of some type, so (cutting out a lot of detail):
typeof(MyType).GetMethod("add").Invoke(null, new [] {arg1, arg2})
This assumes add is static (otherwise first argument to Invoke is the object) and I don't need extra parameters to uniquely identify the method in the GetMethod call.
Use reflection - try the Type.GetMethod Method
Something like
MethodInfo addMethod = this.GetType().GetMethod("add");
object result = addMethod.Invoke(this, new object[] { x, y } );
You lose strong typing and compile-time checking - invoke doesn't know how many parameters the method expects, and what their types are and what the actual type of the return value is. So things could fail at runtime if you don't get it right.
It's also slower.
If the functions are known at compile time and you just want to avoid writing a switch statement.
Setup:
Dictionary<string, Func<int, int, int>> functions =
new Dictionary<string, Func<int, int, int>>();
functions["add"] = this.add;
functions["subtract"] = this.subtract;
Called by:
string functionName = "add";
int x = 1;
int y = 2;
int z = functions[functionName](x, y);
You can use reflection.
using System;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
Type t = p.GetType();
MethodInfo mi = t.GetMethod("add", BindingFlags.NonPublic | BindingFlags.Instance);
string result = mi.Invoke(p, new object[] {4, 5}).ToString();
Console.WriteLine("Result = " + result);
Console.ReadLine();
}
private int add(int x, int y)
{
return x + y;
}
}
}
#Richard's answer is great. Just to expand it a bit:
This can be useful in a situation where you dynamically created an object of unknown type and need to call its method:
var do = xs.Deserialize(new XmlTextReader(ms)); // example - XML deserialization
do.GetType().GetMethod("myMethodName").Invoke(do, new [] {arg1, arg2});
becasue at compile time do is just an Object.