I got CS0079 compile error when I tried to run the code below:
public delegate void MyClassEHandler(MyClassEParam param);
public class MyClassE
{
public static event MyClassEHandler Error
{
add
{
MyClassE.Error = (MyClassEHandler)Delegate.Combine(MyClassE.Error, value);
}
}
}
Error:
CS0079 : The event MyClassE.Error can only appear on the left hand
side of += or -=
Searched around but couldn't figure out how to resolve it.
ADDED:
if (MyClass.Error != null) or
MyClass.Error(null, null);
Get the same CS0079 error.
CS0079 : The event MyClassE.Error can only appear on the left hand
side of += or -=
Can anyone help me on this?
You cannot set an event, you can just add or remove handlers on it. So, as the error says, you should just do:
public delegate void MyClassEHandler(MyClassEParam param);
public static event MyClassEHandler Error
{
add
{
MyClassE.Error += value;
}
remove
{
MyClassE.Error -= value;
}
}
and the Delegate.Combine will work magically for you.
Try this
public delegate void MyClassEHandler(MyClassEParam param);
static MyClassEHandler error;
public static event MyClassEHandler Error
{
add
{
MyClassE.error += (MyClassEHandler)Delegate.Combine(MyClassE.Error, value);
}
remove
{
MyClassE.Error -= (MyClassEHandler)Delegate.Combine(MyClassE.Error, value);
}
}
Refer to the Intercepting add remove of c# event and delegates
Related
Remove all Default event & property
Remove event Click,Load,MouseClick,DoubleClick in userControle
or hildent event
public event EventHandler Click
{
add { this.Click += value; }
remove { this.Click -= value; }
}
Error !!!>>>An unhandled exception of type 'System.StackOverflowException' occurred in WindowsFormsControlLibrary1.dll
this image sample
enter image description here
You can try overriding them and tagging them not browsable.
Here is an example with Click event :
[Browsable(false)]
public new event EventHandler Click
{
add { base.Click += value; }
remove { base.Click -= value; }
}
I got this event handle and how can I do unit test for this
public class MyLearningEvent
{
private event EventHandler _Closed;
public event EventHandler Closed
{
add
{
_Closed -= value;
_Closed += value;
}
remove
{
_Closed -= value;
}
}
public void OnClosed()
{
if (_Closed != null) _Closed(this, EventArgs.Empty);
}
}
Just modified code so that much clear
Thanks
You should not unit test that code. It's a feature which is built into .NET. Your event handling is flawed imho.
add
{
_Closed -= value;
_Closed += value;
}
Probably means that your invokers don't keep track on if they have subscribed or not. That can lead to memory leaks: http://blog.naviso.fr/wordpress/wp-content/uploads/2011/11/MemoryLeaks-English.jpg
A more robust (and thread safe implementation) is:
public class MyLearningEvent
{
public event EventHandler Closed = delegate {};
public void TriggerClosed()
{
Closed(this, EventArgs.Empty);
}
}
But you should not let anyone else trigger that event (make the TriggerClosed private/protected)
Try this method. This assumes MyClass.Close() raises the MyClass.Closed event.
public void ClosedEventHandlerIsNotCalledAfterBeingRemoved()
{
MyLearningEvent Target = new MyLearningEvent();
EventHandler Target_Closed = new EventHandler((sender, e) => { Assert.Fail("Closed EventHandler was raised after being removed."); });
Target.Closed += Target_Closed;
Target.Closed -= Target_Closed;
Target.OnClosed();
}
It it possible to retrive who is subscribing to a event in C#?
example
class MyClass
{
public string Name { get; set; }
}
class Syncronizer
{
public delegate void SynchronizatonEventHandler(MyClass myClass);
public event SynchronizatonEventHandler OnSyncFinished;
}
If i have something like that is it possible for me to see/use the myClass.Name string and use it for logging when the event is subscribed to?
What i want to accomplish is that i want to log every subscribe and unsubscribe from my Syncronizer class.
You can do the following:
class MyClass
{
public string Name { get; set; }
}
class Syncronizer
{
public delegate void SynchronizatonEventHandler(MyClass myClass);
internal event SynchronizatonEventHandler _onSyncFinished;
public event SynchronizatonEventHandler OnSyncFinished
{
add
{
// Perform some code before the subscription.
// Add the event.
_onSyncFinished += value;
// Perform some code after the subscription;
}
remove
{
// Perform some code before the subscription.
// Remove the event.
_onSyncFinished -= value;
// Peroform some code after the subscription.
}
}
}
Here's a working example:
class Syncronizer
{
public delegate void SynchronizatonEventHandler(MyClass myClass);
private event SynchronizatonEventHandler onSyncFinished;
public event SynchronizatonEventHandler OnSyncFinished
{
add
{
var method = new StackTrace().GetFrame(1).GetMethod();
Console.WriteLine("{0}.{1} subscribing", method.ReflectedType.Name, method.Name);
onSyncFinished += value;
}
remove
{
var method = new StackTrace().GetFrame(1).GetMethod();
Console.WriteLine("{0}.{1} unsubscribing", method.ReflectedType.Name, method.Name);
onSyncFinished -= value;
}
}
}
Note that you can not log myClass.Name, since that doesn't exist in the add and remove procedures. I have it logging (to Console.WriteLine) the class and method that subscribed to the event, which is, I think, what you were after.
You need to create an explicit event with your own accessors:
public event SynchronizatonEventHandler OnSyncFinished {
add { ... }
remove { ... }
}
add and remove take a value parameter containing the delegate instance being removed from or added to the event.
For logging purposes, you can get the Method and Target properties of the instance.
Sth. like this should solve your issue:
private event SynchronizatonEventHandler m_OnSyncFinished;
public event SynchronizatonEventHandler OnSyncFinished
{
add
{
// Custom code could be added here...
m_OnSyncFinished += value;
}
remove
{
// Custom code could be added here...
m_OnSyncFinished -= value;
}
}
Following is the Code i am using
class ImpersonatedTab : System.Windows.Forms.TabPage
{
Credentials _cred = new Credentials();
public delegate void Savesetting(TabData Tb);
public event Savesetting TriggerSaveSetting;
public ImpersonatedTab(TabData tb)
{
........
}
private void SaveData()
{
TriggerSaveSetting(_tabdata);
}
private Onclick()
{
SaveData();
}
}
When i call Onclick function within ImpersonatedTab class it returns error saying TriggerSaveSetting is null
I initialize this call like
ImpersonatedTab Tab = new ImpersonatedTab(tb);
Tab.TriggerSaveSetting += new ImpersonatedTab.Savesetting(Tab_TriggerSaveSetting);
i have created events earlier, but am not able to figure out whats wrong with this one.. i am sure should be some silly mistake.
One possible case where this could happen is if you try to call the event from within the constructor of the ImpersonatedTab class. There where you put those .... Also it is a good practice to check if the event handler has been initialized before calling it.
Change your code to this:
public delegate void Savesetting(TabData Tb);
private Savesetting saveSettingDlg;
public event Savesetting TriggerSaveSetting {
add { saveSettingDlg += value; }
remove { saveSettingDlg -= value; }
}
private void SaveData() {
var handler = saveSettingDlg;
if (handler != null) handler(_tabdata);
}
You can now set a breakpoint on the add accessor and SaveData() and verify that event subscription is working correctly. If you do see the add accessor getting called but still get a null for handler then there's a problem with the object reference.
You are trying to invoke the TriggerSaveSetting event handlers before any handler was attached to it. Make sure, to check, the event has been some handlers attached:
private void OnTriggerSaveSetting(_tabdata)
{
if (TriggerSaveSetting != null)
TriggerSaveSetting(_tabdata);
}
I am making a windows forms project in C#, in which I made a class LabelX which inherits System.Windows.Forms.Label, then added a property Mass of float type
Now, my question is how can I handle, when value of Mass is changed.
e.g.:
When user enter value zero or less than zero
I want to fire a message that "Mass can't be zero or negative"
If I am interpreting this correctly, there are two parts to this. First, you need to detect invalid values and throw exceptions. Second, you need to raise an event when the property changes. This can be achieved as follows.
private float mass;
public float Mass
{
get
{
return this.mass;
}
set
{
if (value <= 0.0F)
{
throw new ArgumentOutOfRangeException("Mass cannot be zero or negative.");
}
if (this.mass != value)
{
this.mass = value;
OnMassChanged(EventArgs.Empty);
}
}
}
public event EventHandler MassChanged;
protected virtual void OnMassChanged(EventArgs args)
{
var handler = this.MassChanged;
if (handler != null)
{
handler(this, args);
}
}
To show a message if an invalid entry is made, you should put a try \ catch block around the call to set Mass and catch the ArgumentOutOfRangeException.
Try the following:
// Created an empty form with a LabelX control on it.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Added this event from the property manager.
private void labelX1_MassChanged(object sender, EventArgs e)
{
var label = (LabelX)sender;
if (label.Mass <= 0.0)
MessageBox.Show("Mass is less than or equal to 0");
}
}
public class LabelX : Label
{
private float _mass;
public float Mass
{
get { return _mass; }
set
{
if (!value.Equals(_mass))
{
_mass = value;
OnMassChanged(EventArgs.Empty);
}
}
}
public event EventHandler MassChanged;
protected virtual void OnMassChanged(EventArgs e)
{
if (MassChanged != null)
MassChanged(this, e);
}
}
Outside of your LabelX class, create the following class:
public class MassChangedEventArgs : EventArgs
{
public float Mass { get; private set; }
public MassChangedEventArgs(float mass)
{
this.Mass = mass;
}
}
Also outside of your LabelX class, create the following delegate. This will be your event handler.
public delegate void MassChangedEventHandler(object sender, MassChangedEventArgs e);
Within your LabelX class, create an event to broadcast:
public class LabelX
{
public event MassChangedEventHandler MassChanged;
//the rest of your code here...
}
You'll also want to create a private instance method that will fire your event.
public class LabelX
{
public event MassChangedEventHandler MassChanged;
private void OnMassChanged()
{
if(MassChanged!=null)
this.MassChanged(this, new MassChangedEventArgs(this.Mass));
}
//the rest of your code here...
}
Finally, whenever your Mass property changes, call OnMassChanged. For instance:
public class LabelX
{
private float mass;
public float Mass
{
get
{
return mass;
}
set
{
mass = value;
OnMassChanged();
}
}
public event MassChangedEventHandler MassChanged;
private void OnMassChanged()
{
if(MassChanged!=null)
this.MassChanged(this, new MassChangedEventArgs(this.Mass));
}
//the rest of your code here...
}
When you want to handle that event on a per-instance basis, you just have to register a listener with the MassChanged event of your underlying object and perform whatever actions are necessary.
Events are a common pattern used in the framework. The process typically involves defining a delegate to be used as the event handlers, declaring the event using the handler, defining methods to raise the event, then hooking up to the properties the logic to raise the event.
The message you describe is better done as an Exception but here's an example to define the MassChanged event.
// Define event args if you have additional
// information to pass to your event handlers
public class MassChangedEventArgs : EventArgs
{
public MassChangedEventArgs(int oldMass)
{
OldMass = oldMass;
}
public int OldMass { get; private set; }
}
public class SomeObject
{
// There's a generic event handler delegate that can be
// used so you only need to define the event arguments.
public event EventHandler<MassChangedEventArgs> MassChanged;
// Convenience method to raise the event
protected virtual void OnMassChanged(MassChangedEventArgs e)
{
if (MassChanged != null)
MassChanged(this, e);
}
public int Mass
{
get
{
return mass;
}
set
{
// Your checks here
if (value <= 0)
throw new ArgumentOutOfRangeException("Mass", "Mass can't be zero or negative");
// Should only raise the event if the new value is different
if (value != mass)
{
// Change the mass
MassChangedEventArgs e = new MassChangedEventArgs(mass);
mass = value;
// Raise the event
OnMassChanged(e);
}
}
}
private int mass;
}
After that, it's just a matter of registering handlers to the event and going from there.
I am quite sure you you would like to 'fire' an exception in your case.
This more of a validation logic issue such AOP code contracts concept.
But if you really like to create an event for it you have to at least:
1) create an event storage variable in your label class
public event EventHandler MassChanged;
2) in your property (note that you loose the ability to use code gen functions of c# 3 for
which 'auto' implement the field to store your Mass property value)
public bool Mass
{
get { return _mass; }
set {
// check if value is invalid (0 or less) && that event subscribers exist
if(value<=0 && MassChanged != null) { MassChanged(this, null); }
else // otherwise assign ...
{
_mass = value;
}
}
}
3) create an event handler of type EventHandler
Best to read the msdn article for events: link text
Again I am pretty sure you are not handling exceptions properly in the app
if you need an event for this. I mean there is nothing wrong but events are
usually not used as means of value validations.