What is the assembly to use with Action<T>? I get an error on T not being accepted, that an assembly or namespace is missing.
Method(delegate { OnChange(); });
private static void MethodUsingOtherMethod(Action<T> action)
{
//TODO
}
If I put an extra <T> after MethodUsingOtherMethod then T is accepted, but then the argument in the delegate above is not recognized.
I want to use OnChange() in the second method, to be called from there.
You have to declare your method as a generic method:
private static void MethodUsingOtherMethod<T>(Action<T> action)
{
//TODO
}
Edit: By the way, you only need to do this if you need the passed in delegate to take a parameter of type T. If you need a parameterless method to be passed in, define your method like this:
private static void MethodUsingOtherMethod(Action action)
{
//TODO
}
Action<T> means that you need to pass a delegate accepting 1 argument of type T. So, if you want to pass OnChange, then you can just specify Action without the T.
That way, your code would look like this:
MethodUsingOtherMethod(OnChange);
private static void MethodUsingOtherMethod(Action action)
{
//TODO
}
The error you got about T not being recognized is, because you didn't declare your method as a generic method (done by putting the <T> behind the method name). Because of that, the compiler didn't recognize T as a type argument and tried to look up a type called T, which doesn't exist.
You might want to look up Generics to understand what's going on there:
http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
Related
class Program{
static void Main(){
test11 jhbee = Program.test; //error
test11 yep = delegate { }; //no error
}
static void test() { }
}
delegate void test11(int r);
So I have the delegate test11 which returns void and takes 1 parameter.
whn I try to assign a parameterless method to an instance of test11, the compiler, obviously issues an error but when I assign a parameterless anonymous method to an instance of test11, no error is issued.
I mean, I can see that there is no obstacle for it to work but can you please tell me why is this so? Is there a good reason for this?
From the documentation:
When you use the delegate operator, you might omit the parameter list. If you do that, the created anonymous method can be converted to a delegate type with any list of parameters
So while it appears that way, the created anonymous method is not really parameterless - its parameter list has just not been defined.
As for the reason why this is an option, this answer to a related question might help explain it.
when I try the following in C#, I get an NPE. It's likely not how this should work:
private readonly Dictionary<Type, List<Subscription<Event>>> subscriptionMap = new Dictionary<Type, List<Subscription<Event>>>();;
public void Subscribe<T>(Action<T> action) where T : Event {
...
subscriptionMap[type].Add(new DefaultSubscription<T>(action) as Subscription<Event>);
...
}
Without the as I get compiler errors and with it, it just adds a null to the List. I should note that Subscription and Event are both interfaces. In Java I would simply say <? extends Event> or <? extends Subscription<?>> and this would work with no issues.
Any help on this matter is greatly appreciated!
Generic delegates do not guarantee matching signatures.
What would happen if the Subscribe<T>(Action<T>) were to invoke the Action<T> with a concrete implementation?
Subscribe<ConcreteEvent>((ConcreteEvent e) => { });
...
private void Subscribe<T>(Action<T> action)
where T : Event
{
action(new Event()); // Does not match method signature
subscriptionMap[type].Add(new DefaultSubscription<T>(action) as Subscription<Event>);
}
This would result in a compiler error.
Whether the method signature expects a concrete subtype, or the Event base type, we can not say. The only thing we can say for certain, is that the method takes an argument which implements Event.
Therefore, we need to change the Subscribe method so the signature of Action<T> is known. Since the Action<T> delegate is contravariant, meaning that you can pass any subtype of T into the action, we can change the signature to Action<Event>.
public void Subscribe(Action<Event> action)
{
subscriptionMap[type].Add(new DefaultSubscription<Event>(action));
}
Is there a way to pass different methods as parameter into another method in C#? I have some code like this below
class Program
{
void Action1(string s){...}
string Func1(string s){...}
void RegisterAction(Action<string> action){...}
void RegisterFunc(Func<string, string> func){...}
void Register(????){ }
void Run()
{
RegisterAction(Action1); // ok
RegisterFunc(Func1); // ok
Register(Action1); // ?
Register(Func1); //?
}
}
I want to pass Action1 and Func1 into the same method 'Register', in which I can use reflection to implement my logic. but the Action<string>, Func<string,string>are different delegates, perhaps I will have to deal with Action<int>, Func<object> and many other types I don't want to write the 'register' methods for every action and function.
Any help? Thank you.
There is a base type - MulticastDelegate which itself has a base type of Delegate - but the problem is that you're relying on a method group conversion to a delegate type, and that requires a specific delegate type to convert to. Register(Action1) could convert the method group Action1 to any delegate type returning void and accepting a string - there can be multiple such delegates. How would the compiler know which one you mean?
What you could do is keep your RegisterAction and RegisterFunc methods, but then use a common implementation which stores the delegates in (say) a List<Delegate>.
My understanding of Actions in C# is that they are just a specific version of a delegate, namely one with no parameters and no return type.
If I create a class like this...
class TrainSignal
{
public delegate void TrainsAComing();
public void HerComesATrain()
{
TrainsAComing();
}
}
...it won't compile since I haven't created an instance of the delegate. However if I replace the delegate definition with that of an Action like below it compiles:
class TrainSignal
{
public Action TrainsAComing;
public void HerComesATrain()
{
TrainsAComing();
}
}
I thought perhaps that maybe an Action is static or something like that (thereby allowing us to call it by it's name without instantiating it) but that doesn't seem to be the case.
Can anyone explain why the second code block is legal?
This line
public delegate void TrainsAComing();
defines a public delegate type called TrainsAComing, nested inside your class. This would let users create delegates of type TrainSignal.TrainsAComing, but TrainSignal would have no member to store an instance of such delegate.
In other words, declaration of the delegate does not define a member of delegate type. You need another declaration for that:
class TrainSignal
{
public delegate void TrainsAComing(); // The delegate type
public TrainsAComing OnTrainsAComing; // The member of delegate type
public void HerComesATrain()
{
OnTrainsAComing();
}
}
Action, on the other hand, is already a type, similar to delegate TrainsAComing from your example. Hence, the definition
public Action TrainsAComing;
makes TrainsAComing a member of TrainSignal capable of storing a delegate.
An Action field is a field like any other. It's a ref type, so the field is null initialized. You will receive a NullReferenceException. This is perfectly safe but not useful.
Maybe you meant to actually reference a function?
Action TrainsAComing = () => Console.WriteLine("...");
Or maybe, the confusion comes from the fact that the first code snippet declares a delegate type and the second one declares a field of a delegate type.
I was just experimenting and ended up with the following snippet:
public static class Flow {
public static void Sequence(params Action[] steps) {
foreach (var step in steps)
step();
}
}
void Main() {
Flow.Sequence(() => F1(), () => F2());
Flow.Sequence(F1, F2); // <-- what makes this equiv to the line above?
}
void F1() { }
void F2() { }
I didn't realize that a method name alone was the same as an Action.
What is making this so?
In C#, delegates are nothing more than method pointers. They can point to existing methods in a class, or independent anonymous delegate objects altogether.
This paragraph from the above link should explain what's happening in your code:
Any method that matches the delegate's signature, which consists of the return type and parameters, can be assigned to the delegate. This makes is possible to programmatically change method calls, and also plug new code into existing classes. As long as you know the delegate's signature, you can assign your own delegated method.
That is, when resolving delegate types, what's considered are their signatures, rather than their names.
In your case, your F1() and F2() methods, taking no parameters and returning nothing, have matching signatures with the parameterless Action delegate:
public delegate void Action();
Therefore, they're implicitly convertible to Action.
If you try to pass a method with a different return type or at least one parameter, you'll get a compile-time error as it won't correspond to Action's signature.
Basically, this is kind of what is happening in the background:
void Main()
{
Flow.Sequence(new Action(delegate(){ F1(); }), new Action(delegate(){ F2(); }));
Flow.Sequence(new Action(F1), new Action(F2));
}
They're not EXACTLY equivalent, but they're very close. They would render the same results at run-time, the only difference being that the arguments in the first Sequence invocation would be an Action which invokes an anonymous method which then invokes the static methods F1 and F2; the second Sequence invocation would be an Action which invokes the static methods F1 and F2.
I hope this helps.
The compiler uses an implicit conversion from a method group to a delegate of compatible type (in this case a void returning method taking no arguments), the method names here are irrelevent.