How does the Action delegate with custom classes work when i am not explicitly passing the input parameter type of the referenced method :
DirectMethodCall.PassMethod(x=>x.NoReturnOneParameterMethod(1));
public static void PassMethod(Action<NewClass> c)
{
NewClass op = new NewClass();
c(op);
}
Why do i need to pass the "op" to the Action delegate ?
As comments are a bit messy to post code examples, I'll continue here.
You are not repeating code, you're misunderstanding what you've actually coded. public static void PassMethod(Action<NewClass> c) means
PassMethod requires, as a parameter, a method which executes on a NewClass object.
Maybe this makes it more clear:
void Main()
{
//I am defining the implementation of a method which requires as integer as a parameter, but I don't actually invoke it, just define it.
ExecuteMethod(i => Console.WriteLine(i));
}
public static void ExecuteMethod(Action<int> method)
{
//I don't know what method does, all I know is that I am running it with the number 5.
method(5);
}
ExecuteMethod Takes a method which requires an integer. It doesn't know what the method does. All it knows is that it requires an int, and it passes it the value 5
The actual code is from the caller:
i => Console.WriteLine(i)
Here, i is set to 5, and so the result is 5 being printed to the console.
Your PassMethod is expecting a delegate which accepts one parameter of type NewClass and it calls NoReturnOneParameterMethod() with parameter 1 and has a return type of void
Action<T> means it is a delegate that takes type T as its argument and has return type of void.
See: MSDN Action
Related
I'm using a method with this as the 1st parameter:
Action<IFieldsetter<Contact>>
How do I read this? Does is mean that this must be an Action object where the Action constructor is constrained to accept only something that implements IFieldsetter? And it looks like IFieldsetter itself is being constrained, but I don't understand this part at all.
It's not an actual constraint, but just the type it needs. So, that method's first parameter is an Action (i.e. delegate), which has only one parameter, and that parameter is a IFieldsetter<Contact>, whatever that means. My guess is that IFieldsetter exposes a setter and in this case it must handle the type Contact, but you should be the one who knows for real what they are and do! Post the code of this interface and this class if you need further help.
For example, if it was Action<IEnumerable<String>>, it would mean that the delegate receives a list of strings as a parameter. Here's some code:
// Your method with the *special* parameter.
private void ChrisMethod(Action<IEnumerable<String>> method)
{
string[] exampleList = { "First", "Second", "Third" };
method(exampleList);
}
// The method that can be used as parameter.
private void ParameterMethod(IEnumerable<String> list)
{
foreach(string str in list)
Console.WriteLine(str);
}
public void Main()
{
ChrisMethod(ParameterMethod);
}
A constraint on a type parameter is a different thing. You can learn more about that here.
A C# System.Action (MSDN) is a delegate object where Action<T> is the equivalent of a delegate function matching void FunctionName(T). So you can set it to a function and later on call that function.
The section generics block <Contact> applies to the IFieldsetter, so you have an Action that takes an argument of IFieldsetter<Contact>. Without knowing anything about the IFieldsetter I can't tell you what it's going to do with the Contact generic argument there.
In order to use this, you'll can have something resembling the following:
void Main()
{
FunctionThatDoesStuff(SetField);
}
void FunctionThatDoesStuff(Action<IFieldsetter<Contact>> action)
{
var setter = new IFieldsetter<Contact>();
action(setter);
}
void SetField(IFieldsetter<Contact> setter)
{
}
This is nested generic type parameter. From the outermost layer, you can see that this is an Action<T> delegate. And the delegate needs an argument of type T. In this case, T is replaced by IFieldsetter<Contact>. i.e. Action<IFieldSetter<Contact>> needs an argument of type IFieldSetter<Contact>. Now the IFieldSetter<T> interface sets a field of type T. And in this case, T is replaced by Contact so IFieldSetter<Contact> sets a field of type Contact.
Let's sum up: Action<IFieldsetter<Contact>> represents an Action delegate that needs an argument of type IFieldSetter which can set a field of type Contact. Now do you understand?
Action<IFieldsetter<Contact>> means Action delegate accepts a parameter of type that implements a generic interface IFieldsetter. suppose a class is implemented with IFieldsetter intercae with Contact as the generic parameter as shown below.
public class Test: IFieldsetter<Conatct>
{
}
Now instance of this test class can be passed as parameter to the Action deletegate.
I'm trying to register a generic that derives from a base class in the following way, but getting the error :
cannot convert MyCallback<T> expression to type MyCallback<Event>
I was hoping the constraints would make this possible but am I missing something?
public class Event
{ };
public delegate void MyCallback<T>(T arg1) where T : Event;
static class EventDispatcher
{
public static Dictionary<string, MyCallback<Event>> eventTable = new Dictionary<string, MyCallback<Event>>();
static void RegisterCallback<T>(MyCallback<T> callback) where T : Event
{
eventTable.Add("test", callback);
}
}
When you have a MyCallback<Event> you're saying that you have a method that can take any type of event. It can accept an EventOne, or an EventTwo, or a SomeOtherEvent.
Let's say I call RegisterCallback and pass in a delegate pointing to a method with this signature:
public static void Foo(SomeOtherEvent arg)
If your code would work, and I could assign that to a MyCallback<Event>, then I could pass in an EventOne instance to that method when calling it. That's obviously a problem.
There's a term for that; you're expecting MyCallback to be covariant with respect to it's generic argument. In fact, it's contravariant. If I have a method that can accept any type of event, I can clearly pass in a SomeEvent, or a SomeOtherEvent, meaning I could assign a MyCallback<Event> to a MyCallback<SomeOtherEvent>, rather than the other way around.
If you want to tell the compiler that, "I know that this method cannot actually be called with any type of event, but I want you to allow this check and only fail at runtime if the given argument is not of the proper type." then you can do that, assuming you actually have a way of ensuring you call each callback with the proper arguments. You can't just do a cast either; you need to wrap the method in a new method that does the cast:
eventTable.Add("test", e => callback((T)e));
You need to have the type parameter be part of the EventDispatcher class:
public class EventDispatcher<T> : where T : Event {
public Dictionary<string, MyCallback<T>> eventTable = new Dictionary<string, MyCallback<T>>();
void RegisterCallback(MyCallback<T> callback) {
eventTable.Add("test", callback);
}
}
This is because the MyCallback<Event> declared in eventTable is not going to be compiled into the same type declared in RegisteredCallback when written like your example.
I'm writing a class that implements 3rd party interface. One of the functions of the interface accepts a parameter of type "object".
Within the function, I need to call a function that I want to pass in to the function as the object parameter, but I can't get it to work.
Example:
public class ABC : Ixyz
{
...
public void DoSomething(object parameter);
{
// Here I will execute the function passed in
}
...
}
public void MySomething()
{
...
}
public void SomeFunction()
{
ABC myABCobject = new ABC();
myABCobject.DoSomething(MySomething);
}
When I try to compile this, I get the following error:
Cannot convert method group 'MySomething' to non-delegate type
'object'. Did you intend to invoke the method?
I have the feeling that I should be doing something with delegates, but since I'm implementing a 3rd party interface, I can't change the signature of the function.
Can I somehow pass in a reference to this function that's expecting an "object"? I would think that I could, since Delegate inherits from Object.
try casting your parameter to the call to DoSomething as an action - e.g.
myABCobject.DoSomething((Action)MySomething);
I'm pretty sure that'll work...
in fact I just tested it and it does - you can cast the action back in the DoSomething method and invoke it - e.g.
var newparameter = (Action) parameter;
newparameter();
I need to be able to pass an arbitrary method to some function myFunction:
void myFunction(AnyFunc func) { ... }
It should be possible to execute it with other static, instance, public or private methods or even delegates:
myFunction(SomeClass.PublicStaticMethod);
myFunction(SomeObject.PrivateInstanceMethod);
myFunction(delegate(int x) { return 5*x; });
Passed method may have any number of parameters and any return type. It should also be possible to learn the actual number of parameters and their types in myFunction via reflection. What would be AnyFunc in the myFunction definition to accommodate such requirements? It is acceptible to have several overloaded versions of the myFunction.
The Delegate type is the supertype of all other delegate types:
void myFunction(Delegate func) { ... }
Then, func.Method will give you a MethodInfo object you can use to inspect the return type and parameter types.
When calling the function you will have to explicitly specify which type of delegate you want to create:
myFunction((Func<int, int>) delegate (int x) { return 5 * x; });
Some idea of what you're trying to accomplish at a higher level would be good, as this approach may not turn out to be ideal.
Have the method accept a Delegate, rather than a particular delegate:
void myFunction(Delegate func)
{
}
I have a class that has to receive methods in order to call them as well as doing other executions. These methods have to be used many times and for many different users so the simpler the better.
To deal with this I have two methods:
void Receive(Action func)
{
// Do some things.
func();
}
T Receive<T>(Func<T> func)
{
// Do some things.
return func();
}
(Actually I have 34 methods to be able to receive any of the different Action or Func defined.)
Then, I want to be able to pass any method as a parameter to the Receive function, to be able to do something like this:
void Test()
{
Receive(A);
Receive(B);
}
void A()
{
}
int B()
{
return 0;
}
Just like this, it gives me one error in Receive(B):
The call is ambiguous between the following methods or properties: 'Class1.Receive(System.Action)' and 'Class1.Receive<int>(System.Func<int>)'
Ok, the signature is the same (although no error is shown if I don't use the methods).
If I remove the Receive(Action) method, I get in Receive(A) the following error:
The type arguments for method 'Class1.Receive<T>(System.Func<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
But my type in this case is void and it is forbidden to use it as a generic parameter.
So, is there a way to have my Receive method without using any explicit cast of Action or Func?
No you can't do this - void is not a valid return type for Func<T>. The best you could do is to wrap it in a Func<object>:
Receive(() => { A(); return null; });
Try specifying the generic type parameter explicitly:
Receive<int>(B);