No overload for matches delegate - c#

I have this method:
public static void InsertPageNumbering(object sender, CreateAreaEventArgs e, BaseOracleUtils OraCon)
{
PCK.SetData(OraCon);
}
How to assign it to event:
compositeLink.CreateMarginalFooterArea += BaseSettingsInit.InsertPageNumbering;
CreateMarginalFooterArea have this parameters:
public delegate void CreateAreaEventHandler(object sender, CreateAreaEventArgs e);
Is any option assign method (with keeping OraCon parameter)?

The compiler says it all.
CS0123 - No overload for InsertPageNumbering matches delegate CreateAreaEventHandler.
If you were able to assign the method to the event what should happen during invocation of the event? What value of BaseOracleUtils should be passed as the OraCon parameter?
Unfortunately you are not able to provide default for the last parameter either. The only solution I see is to either extend the delegate to accept one more parameter.
Or create a wrapper around your InsertPageNumbering method such as
public static void InsertPageNumberingWrapper(object sender, CreateAreaEventArgs e)
{
InsertPageNumbering(sender, e, GetBaseOracleUtils());
}
which would provide some reasonable value as the last parameter to it. And then add this wrapper to the event. GetBaseOracleUtils() could pull the value out of somewhere (I have no idea what are you trying to solve and where should the value come from).

Related

Why We Need EventArgs class in C#?

I know that the purpose of event keyword just to used in pair with += operator to make list of delegate. And when constructing delegate we can make any signature (of parameter) for method that compatible with that delegate.
For example I create delegate
public delegate void StartEventHandler(object sender, StartEventArgs e);
with two parameter: the first with the type object and the second with the type StartEventArgs. But in many article that I found on the internet, the second parameter for that delegate must inherited EventArgs type. Why we do this instead to make the second parameter come/inherited from arbitrary type?
You don't need to and I'm sure the code will still compile if you used an arbitrary base class but it is a convention.
Conventions are good because it makes it easier to understand for people who are not familiar with your code already. If I subscribe to an event in C# I expect a certain method signature.
It is also good because it makes different types of events interchangeable.
For example, say you have three delegates
public delegate void AEventHandler(object sender, AEventArgs e);
public delegate void BEventHandler(object sender, BEventArgs e);
public delegate void CEventHandler(object sender, CEventArgs e);
You could write a generic method that conforms to all three delegates because all the args objects inherit from the same base class.
public void eventMethod(object sender, EventArgs e) {
// Any one of the events fired
}
public void subscribeToEvents() {
eventA += new AEventHandler(this.eventMethod);
eventB += new BEventHandler(this.eventMethod);
eventC += new CEventHandler(this.eventMethod);
}
And even cast if you know what types to expect
public void eventMethod(object sender, EventArgs e) {
// Any one of the events fired
if (e is BEventArgs) {
// Event type B fired
var eventB = e as BEventArgs;
eventB.doSomething()
}
}

Why can't I just use EventHandler<int> instead of deriving from EventArgs

The documentation for EventHandler<TEventArgs> says:
The second parameter is a type derived from EventArgs and supplies
any fields or properties needed to hold the event data.
and it seems to be generally recommended throughout the .Net documentation.
However it turns out that I can do the following which works just fine:
public event EventHandler<int> Panned;
and invoke the event handler as:
int value = 10;
if (Panned != null)
{
Panned(this, value);
}
and on the observer side:
subject.Panned += (sender, e) =>
{
Console.WriteLine(e);
};
To me this seems better than littering the code with little classes that inherit from EventArgs or having a generic EventArgs as proposed by Does .NET have a built-in EventArgs<T>?
So why is it required that I inherit the EventHandler generic argument from EventArgs?
If all you need to do is pass an int to the handler then what you are doing is fine.
It used to be the case (before .NET 4.5) that the EventHandler type argument TEventArgs was constrained to inherit from EventArgs but not anymore:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
The fact that MS dropped the constraint should tell you that they were being too strict and what you are doing is fine.
In the case that you need to pass a complex type to the handler then you might aswell inherit EventArgs for reasons of polymorphism. Also, the EventArgs.Empty member is useful.
This is just a convention. In fact, you don't even have to use the EventHandler<> generic delegate. You could have:
public event Action SomeEvent;
public void OnAction()
{
var a = this.SomeEvent;
if (a != null)
{
a();
}
}
Of course, the convention is there for a reason. As far as I know, every standard .NET event follows the pattern of using a void-returning delegate that takes an object parameter and a second parameter of EventArgs or a derived type. This makes it easy to use these events without having to refer to the documentation each time.
Silly, Silly, Silly!
Will this work?...
class Program
{
public static event Func<int> SomeEvent;
static void Main(string[] args)
{
SomeEvent += () => 7;
SomeEvent += () => 8;
var a = SomeEvent();
Console.WriteLine(a);
}
}
I tried it: it does! Of course, it's very odd to have an event where the delegate has a return value, because it's not obvious which handler's value will be returned to the caller if there are multiple attached handlers. In the above example, it turns out that 8 is written to the console.
Interesting but, I suspect, useless ;-)
Would You Ever Use This?
I don't think it would ever be sensible to have a non-void returning delegate type, as in my example. However, you might consider using a delegate whose parameters are value types (structs, not classes) for performance reasons. It might be possible to use events without incurring the garbage collection penalty of allocating EventArgs objects on the heap.

Call method without parameters

I have a quick C# question.
I have a list that I need to pass onto a method. So I did this:
Form2 f2 = new Form2(JogadoresList);
f2.novoJogo(JogadoresList);
And on another class:
public void novoJogo(List<Jogadores> JogadoresList)
{}
But now I want to call the novoJogo method from a
private void button1_Click(object sender, EventArgs e)
{
}
method. How can I call the novoJogo method if I don't have parameters to pass onto it and don't want to replace the novoJogo's list? Thank you.
You can just call novoJogo passing null value as parameter:
novoJogo(null);
Or an empty list:
novoJogo(new List<Jogadores>());
Also in the novoJogo method, you could define the List<> as an optional parameter:
public void novoJogo(List<Jogadores> JogadoresList=null)
{}
Then, you can call it without passing the argument in the the click event as I show below:
private void button1_Click(object sender, EventArgs e)
{
novoJogo();
}
Either the method needs the list, or it doesn't. So the fact you are asking this is... troubling.
However, you have a couple options. Just pass null:
private void button1_Click(object sender, EventArgs e)
{
//Hopefully you held onto that reference!
f2.novoJogo(null);
}
Or use default arguments/optional parameters:
public void novoJogo(List<Jogadores> JogadoresList = null)
{}
private void button1_Click(object sender, EventArgs e)
{
//Hopefully you held onto that reference!
f2.novoJogo();
}
In both cases, make sure that novoJogo will be OK with a null list passed to it (NRE is really easy to get here if you weren't careful). And consider if your design makes sense here, if only part of the function needs the list, should that really have been two functions instead of one?
Change the access-level of JogadoresList to public static or internal static so you can access it via button1_click.

How can I know which method called event handler

I have two methods:
private void RvListen_OPT()
private void RvListen_FUT()
On a certain event, both call:
void OnRvMessageReceived(object sender, SigRvMessageEventArgs args)
When OnRvMessageReceived is called, how can I check which of the two methods called it? I know it can be done using the object sender, but I'm not sure how to do it.
If you can edit the SigRvMessageEventArgs class you could add a field to it which you set differently in the two calls.
sender will (usually) give you the object that called the event. It may not because its up to the caller to actually set this.
That said, I"m not sure it should matter. If the call depends on who called it, maybe they need to be setup as separate events... Or, as Jackson mentioned, the args variable could be set to allow the OnRvMessageReceived event can respond to that.
Set sender to a string if you can't change SigRvMessageEventArgs to take an additional property... But the best approach would be to modify SigRvMessageEventArgs if possible.
private void RvListen_OPT()
{
OnRvMessageReceived("RvListn_OPT()", new SigRvMessageEventArgs())
}
private void RvListen_FUT()
{
OnRvMessageReceived("RvListn_FUT()", new SigRvMessageEventArgs())
}
void OnRvMessageReceived(object sender, SigRvMessageEventArgs args)
{
if(sender.ToString() == "RvListn_OPT()"){
// do work
}
else if(sender.ToString() == "RvListn_FUT()"){
// do work
}
}

EventHandler delegate accepts methods with the following signature, but event implementing EventHandler doesn’t

Assuming we declare a class DerivedEventArgs:
public class DerivedEventArgs : EventArgs { ... }
then EventHandler delegate is able to accept methods with the following signature:
public static void Some_Method(object o, DerivedEventArgs e) { ... }
But if we try to subscribe a method with the above signature to the event implementing EventHandler delegate:
public event EventHandler MyEvent;
, then we get an error. Why is that?
thanx
Suppose the code raising the event specified a value which wasn't a DerivedEventArgs - what would you expect it to do? Basically you'd lose type safety.
EDIT Note that you can do it the other way round - you can subscribe to an event with a more specific parameter type using a method with a less specific parameter type - because the event is still guaranteeing that it will call the handler with something compatible. Here's an example:
using System;
class Test
{
public class DerivedEventArgs : EventArgs { }
public EventHandler<DerivedEventArgs> SpecialistEvent;
static void Main()
{
Test t = new Test();
t.SpecialistEvent += GeneralHandler;
}
static void GeneralHandler(object sender, EventArgs e)
{
}
}
MyEvent(this, EventArgs.Empty)
would try to pass a regular EventArgs to DerivedEventArgs in
Some_Method(object o, DerivedEventArgs e)
and then if Some_Method tried to do an
e.PropertyInDerivedClass
it'd fail.
try using an EventHandler<T> for your event, where T is your DerivedEventArgs class.
From MSDN EventHandler documentation...
EventHandler is a predefined delegate that specifically represents an event handler method for an event that does not generate data. If your event does generate data, you must supply your own custom event data type and either create a delegate where the type of the second parameter is your custom type, or use the generic EventHandler< TEventArgs > delegate class and substitute your custom type for the generic type parameter.
The EventHandler Delegate was not made to do what you're trying to do. It's a simple convenience delegate for use in cases where event data is unimportant. The event that utilizes this delegate type may send a EventArgs with the least derived event argument type possible. That means your delegate should be ready to receive anything.
But in your example, you're specifying a more derived event argument type in your handler. Hence, if allowed by the compiler, your code can actually receive another EventArgs type that's not what you expect but defined as your derived type; breaking type safety as mentioned earlier.

Categories

Resources