C# delegate for two methods with different parameters - c#

I am using the following methods:
public void M1(Int32 a)
{
// acquire MyMutex
DoSomething(a);
// release MyMutex
}
and
public void M2(String s, String t)
{
// acquire MyMutex
DoSomethingElse(s, t);
// release MyMutex
}
From what I have found so far it seems that it is not possible to use a single delegate for two methods with different signatures.
Are there any other alternatives to write something like this:
public void UsingMutex(...)
{
// acquire MyMutex
...
// release MyMutex
}
UsingMutex(M1);
UsingMutex(M2);
All I can think for the moment is to use two delegates and a boolean flag to know which delegate to call, but it is not a long term solution.
It is possible to combine generics with delegates? And if so, do you have some links for any kind of documentation?
Environment: C# 2.0

Absolutely you can mix delegates with generics. In 2.0, Predicate<T> etc are good examples of this, but you must have the same number of args. In this scenario, perhaps an option is to use captures to include the args in the delegate?
i.e.
public delegate void Action();
static void Main()
{
DoStuff(delegate {Foo(5);});
DoStuff(delegate {Bar("abc","def");});
}
static void DoStuff(Action action)
{
action();
}
static void Foo(int i)
{
Console.WriteLine(i);
}
static void Bar(string s, string t)
{
Console.WriteLine(s+t);
}
Note that Action is defined for you in .NET 3.5, but you can re-declare it for 2.0 purposes ;-p
Note that the anonymous method (delegate {...}) can also be parameterised:
static void Main()
{
DoStuff(delegate (string s) {Foo(5);});
DoStuff(delegate (string s) {Bar(s,"def");});
}
static void DoStuff(Action<string> action)
{
action("abc");
}
static void Foo(int i)
{
Console.WriteLine(i);
}
static void Bar(string s, string t)
{
Console.WriteLine(s+t);
}
Finally, C# 3.0 makes this all a lot easier and prettier with "lambdas", but that is another topic ;-p

Yes, it's possible to combine generics with delegates.
public delegate void Action<T>(T x);
public delegate void Action<T,U>(T x, U y);
public void UsingMutex<T>(Action<T> x, T t) {
// acquire mutex...
x(t);
// release mutex...
}
public void UsingMutex<T,U>(Action<T,U> x, T t, U u) {
// acquire mutex...
x(t, u);
// release mutex...
}
But you still have to handle different number of parameters using overloads.

If you look at the Func<T> and Action<T> delegates in the framework, you'll see that they define a number of similar delegates with different number of parameters. You can use generics, but that doesn't solve the number of arguments issue you're talking about.

Related

Call Method based on Type of Parameter

I have an object that can be of type AudioRequest or VideoRequest. Both classes inherit from Request. I have this class:
public static DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
I want to be able to call DoThings.HandleRequest(r) where r can be either a VideoRequest or AudioRequest and have it call the correct one. Is that possible? I have no control over the *Request classes, so I can't do anything to them. I do have control of the DoThings class and the code that calls HandleRequest. This is the code that calls it, it is WebAPI:
public Response Post(Request input)
{
return DoThings.HandleRequest(input);
}
The code above gives the error Argument 1: cannot convert from 'Request' to 'AudioRequest'.
The original code that I was cleaning up had this:
if (input.GetType() == typeof(AudioRequest))
{
var audioRequest = (AudioRequest)input;
DoThings.HandleRequest(audioRequest);
}
else if (input.GetType() == typeof(VideoRequest))
{
var videoRequest = (VideoRequest)input;
DoThings.HandleRequest(videoRequest);
}
But I figured there was a cleaner way to do this.
Based on the information you've provided so far, your question appears to be a duplicate of How to call a function dynamically based on an object type. I agree with the answer, that the fact that you want to do this suggests you should rethink the design. But, you can use dynamic to accomplish what you want.
Here's a simple console program that demonstrates the basic idea:
class Program
{
static void Main(string[] args)
{
A b = new B(), c = new C();
M(b);
M(c);
}
static void M(A a)
{
WriteLine("M(A)");
M((dynamic)a);
}
static void M(B b)
{
WriteLine("M(B)");
}
static void M(C c)
{
WriteLine("M(C)");
}
}
class A { }
class B : A { }
class C : A { }
The output is:
M(A)
M(B)
M(A)
M(C)
As you can see, in each case the M(A) method is called first, and then the appropriate M(B) or M(C) overload is called from M(A).
In your own example, this could look something like this:
public static DoThings
{
public static void HandleRequest(Request r)
{
// Dynamic dispatch to actual method:
HandleRequest((dynamic)r);
}
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
Note that dynamic does incur a run-time cost, particularly the first time a method is called with a given run-time type. But depending on the frequency and complexity of these "requests", using dynamic could be the cleanest way out of the current situation.
C# will call the appropriate function that matches the arguments and their types.
That being said, both of your functions accept AudioRequest, I believe one of those should accept a VideoRequest.
public static DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
If for some reason you must have two different functions that take only AudioRequest you can differentiate between two function with an extra parameter
public static class DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(AudioRequest r, bool UseAlternativeMethod)
{
// Do other things.
}
}
Simply having a second parameter will call the second method regardless of it's value.
This isn't a best practices solution as you'd rather discriminate between them by accurately renaming the method name to be accurate but in practice you don't always have a choice.

Why can methods not work syntactically like func/action delegates? [duplicate]

This question already has answers here:
In c#, why can't lambdas have extensions?
(2 answers)
Closed 6 years ago.
On the way home I had an idea: create Func/Action extensions which would allow some nice syntactic sugar in c#.
Theoretical example... create an extension for various permutations of Func/Action which allow you to time the method's execution.
As I arrived home and tried an example, I found this is not possibly. I believe it is a shortcoming/inconsistency in c#. Delegates and methods are one in the same (in theory).
public static class Extensions
{
public static void Time(this Action action)
{
// Logic to time the action
action();
}
}
public class Example
{
public void Main()
{
Action action = RunApp;
Action actionLambda = () => { };
Action actionDelegate = delegate () { };
Extensions.Time(RunApp); // Works
Extensions.Time(() => { }); // Works
Extensions.Time(delegate() { }); // Works
Extensions.Time(action); // Works
Extensions.Time(actionLambda); // Works
Extensions.Time(actionDelegate); // Works
action.Time(); // Works
actionLambda.Time(); // Works
actionDelegate.Time(); // Works
((Action) RunApp).Time(); // Works
((Action) delegate () { }).Time(); // Works
((Action) (() => { })).Time(); // Works
// These should all be the same!
RunApp.Time(); // No good: "Example.RunApp() is a method which is not valid in the given context"
() => { }.Time(); // No good: Operator '.' cannot be applied to operand of type 'lambda expression'"
(() => { }).Time(); // No good: Operator '.' cannot be applied to operand of type 'lambda expression'"
delegate() { }.Time(); // No good: "Operator '.' cannot be applied operand of the type 'anonymous method'"
}
public void RunApp()
{
// Stuff...
}
}
I understand Func/Action are newer additions to c# compared to delegates and method groups, but why can they all not act the same?
Action just nicely encapsulates delegates in a simple way without having to explicitly declare your delegates. In C# delegate is the language mechanism for capturing a method as a type. A type is what you need to create an extension method on.... so, simplifying back to delegates...
public static class Extensions
{
public delegate void Del();
public static void Time(this Del action)
{
// Logic to time the action
action();
}
}
class Program
{
static void Main(string[] args)
{
((Extensions.Del)(() => { })).Time();
}
}
the language won't automatically cast Methods to Del, you need to explicitly do so. Methods themselves aren't a type, delegates are the mechanism to capture them. Fundamentally, in c#, delegate is not the same as method. It's C#s solution to having typesafe pointers to methods.
Another thing to keep in mind is you can do :-
public static class Extensions
{
public delegate void Del();
public delegate void Del2();
public static void Time(this Del action)
{
// Logic to time the action
action();
}
public static void Time(this Del2 action)
{
// Logic to time the action
action();
}
public static void Time(this Action action)
{
// Logic to time the action
action();
}
}
class Program
{
static void Main(string[] args)
{
((Extensions.Del)(() => { })).Time();
((Extensions.Del2)(() => { })).Time();
((Action)(() => { })).Time();
(() => { })).Time(); // no way to know what type this should be coerced to
}
}
Now your methods could be captured as many different types.

params parameter and normal parameters

using System;
using System.Collections.Generic;
namespace Generics
{
class Minivan
{
public void foo(int z, int x)
{
Console.WriteLine("foo with two parameters");
}
public void foo(params int[] z)
{
Console.WriteLine("foo with two params parameter");
}
}
class D
{
public static void Main()
{
Minivan car3 = new Minivan();
car3.foo(10,20); // which method will be called here!!!
}
}
}
which foo method is called? and why?
in a simple sentence "more specific is better than less specific"
so public void foo(int z, int x) will be called.
it is because of method overload resolution rules in C#.
you can read more in this answer
Compiler will choose a method with explicit parameters (as said in c# spec). But if you'll call method with 3 params the params implementation'll be called
To put it simply, the one with the two explicit parameters is chosen here.
I don't claim to know the reasoning behind that decision in the spec, but I would image it goes something like "You went to the trouble to explicitly handle the case where two parameters are passed in, so that would be the only sensible choice of method to choose"
this is a simple overload, when you explicitly call the function with two parameters it will call public void foo(int z, int x)

How to create an Action from another with an additional parameter?

Is there a class available in the .Net Framework which wraps an Action and another parameter just like EnhancedAction in the following example?
private void Test(string s)
{
// I would like :
// Method1(EnhancedAction.Create(Method2, s));
// But I must write :
Method1(i => Method2(i, s));
}
private void Method1(Action<int> myAction)
{
myAction(1);
}
private void Method2(int i, string s)
{
}
You've already shown how to write the code; you merely need to create your own class that has that exact solution to implement the method you're asking for:
class EnhancedAction
{
public static Action<T1> Create<T1, T2>(Action<T1, T2> action, T2 parameter2)
{
return parameter1 => action(parameter1 , parameter2);
}
}
Although I fail to see how this is easier to write out than just using the lambda directly.
I found Umbrella which provides what I was looking for : http://umbrella.codeplex.com/SourceControl/latest#Main/Src/Umbrella/Binding/CurryExtensions.cs
Though it doesn't seem very active lately.

C#: Creating an instance of an abstract class without defining new class

I know it can be done in Java, as I have used this technique quite extensively in the past. An example in Java would be shown below. (Additional question. What is this technique called? It's hard to find an example of this without a name.)
public abstract class Example {
public abstract void doStuff();
}
public class StartHere{
public static void main(string[] args){
Example x = new Example(){
public void doStuff(){
System.out.println("Did stuff");
}
};
x.doStuff();
}
}
Now, my main question would be, can this also be done in C#, and if so, how?
The Java technique is called "Anonymous inner class", and there is no equivalent in C#.
With lamba expressions and class initializers you can get the same behaviour with a bit of effort.
public class Example {
public Action DoStuff;
public Action<int> DoStuffWithParameter;
public Func<int> DoStuffWithReturnValue;
}
class Program {
static void Main(string[] args) {
var x = new Example() {
DoStuff = () => {
Console.WriteLine("Did Stuff");
},
DoStuffWithParameter = (p) => {
Console.WriteLine("Did Stuff with parameter " + p);
},
DoStuffWithReturnValue = () => { return 99; }
};
x.DoStuff();
x.DoStuffWithParameter(10);
int value = x.DoStuffWithReturnValue();
Console.WriteLine("Return value " + value);
Console.ReadLine();
}
}
One problem with this solution that I just realized is that if you were to create fields in the Example class, the lambda expressions would not be able to access those fields.
However, there is no reason that you could not pass the instance of Example to the lambda expressions which would give them access to any public state that example might hold. AFAIK that would be functionally equivalent to the Java Anonymous Inner Class.
P.S. If you are going to vote an answer down, do us all a favour and add a comment as to why you disagree :-)
Typically, problems that are solved with anonymous inner classes in Java are solved in a much cleaner fashion using delegates in .Net. Your example is a little too simplistic to determine your intent. If your intent by using the abstract class is to pass around a "behavior" think about just using an Action delegate instead.
public class StartHere{
public static void main(string[] args){
Action doStuff = () => Console.WriteLine("Did stuff");
executeSomething(doStuff);
}
public static void executeSomething(Action action)
{
action();
}
}
That can't be done in C#; you need to declare a new class type. The closest you can get in C# is probably a named nested class:
public class StartHere{
private class Foo : Example {
public override void doStuff()
{
Console.WriteLine("did stuff");
}
}
public static void Main(string[] args){
Example x = new Foo();
x.doStuff();
}
}
This is not supported in C#, and if it were up to me it shouldn't be so either.
The proliferation of inner classes in java is mainly due to the lack of delegates or lambdas, which C# has. So while this type of functionality currently is "your only hope" in java, you can usually use other mechanisms in C# to achieve the same ends. Java feels like playing the piano with one hand in this regard.
(Admittedly a lot of us have gotten quite good at this one-handed playing; and now it seems like we have to wait at least until java 8 for closures...)
Since your class represents only an action, you can use a delegate in your case, there is an existing delegate :
public delegate void Action();
This is the exact equivalent of your class.
And the déclaration of your anonymous class is even cleaner :
Action action = () => Console.WriteLine("Hello world");
action(); // invoke
you can even use closure :
public void Hello(string name)
{
Action action = () => Console.WriteLine("Hello " + name);
action(); // will call the above lambda !
}
While all good answers, most of the work arounds suggested rely on C# 3.0
So, for the sake of completeness, I'll add another solution that uses neither lambdas nor Func type (Granted that, as Matt Olenik mentioned in the comments, one could generalize the below delegates to work the same way.). For those, like me who may still be working with C# 2.0. Maybe not the best solution, but it works.
public class Example
{
public delegate void DoStuffDelecate();
public DoStuffDelecate DoStuff;
public delegate void DoStuffWithDelecate(int n);
public DoStuffWithDelecate DoStuffWithParameter;
public delegate int DoStuffWithReturnDelecate();
public DoStuffWithReturnDelecate DoStuffWithReturnValue;
}
class Program
{
static int MethodWithReturnValue()
{
return 99;
}
static void MethodForDelecate()
{
Console.WriteLine("Did Stuff");
}
static void MethodForDelecate(int n)
{
Console.WriteLine("Did Stuff with parameter " + n);
}
static void Main(string[] args)
{
var x = new Example();
x.DoStuff = MethodForDelecate;
x.DoStuffWithParameter = MethodForDelecate;
x.DoStuffWithReturnValue = MethodWithReturnValue;
x.DoStuff();
x.DoStuffWithParameter(10);
int value = x.DoStuffWithReturnValue();
Console.WriteLine("Return value " + value);
Console.ReadLine();
}
}
You are able to accomplish this with Mocking in .NET. However there is no in-language support for this feature, I think it will be available in C# 4.0. There are a number of libraries out there for Mocking, including:
Moq
RhinoMock
In short no, you have to define it as separate sub class. I think this feature is coming C# 4.0 though?
Edit: No it's not coming C# 4.0 I made that up.

Categories

Resources