Replies: 8 comments 1 reply
-
Similar to a property, an event exposes syntax to add and remove callbacks to something easily, but that something could be anything at all. In a class, an auto event (similar to an auto property) generates a simple implementation using a backing field. So if you changed your interface to a class, you would generate this: [CompilerGenerated]
private PropertyChangedEventHandler m_PropertyChanged;
public event PropertyChangedEventHandler PropertyChanged
{
[CompilerGenerated]
add
{
PropertyChangedEventHandler propertyChangedEventHandler = this.m_PropertyChanged;
PropertyChangedEventHandler propertyChangedEventHandler2;
do
{
propertyChangedEventHandler2 = propertyChangedEventHandler;
PropertyChangedEventHandler value2 = (PropertyChangedEventHandler)Delegate.Combine(propertyChangedEventHandler2, value);
propertyChangedEventHandler = Interlocked.CompareExchange(ref this.m_PropertyChanged, value2, propertyChangedEventHandler2);
}
while ((object)propertyChangedEventHandler != propertyChangedEventHandler2);
}
[CompilerGenerated]
remove
{
PropertyChangedEventHandler propertyChangedEventHandler = this.m_PropertyChanged;
PropertyChangedEventHandler propertyChangedEventHandler2;
do
{
propertyChangedEventHandler2 = propertyChangedEventHandler;
PropertyChangedEventHandler value2 = (PropertyChangedEventHandler)Delegate.Remove(propertyChangedEventHandler2, value);
propertyChangedEventHandler = Interlocked.CompareExchange(ref this.m_PropertyChanged, value2, propertyChangedEventHandler2);
}
while ((object)propertyChangedEventHandler != propertyChangedEventHandler2);
}
} When you then call In an interface however you can't create a field. Instead you can make a protected property, and manually write the event logic yourself. However that won't allow you to make it thread safe simply, since you cant use using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
namespace ClassLibrary1
{
public interface IDimTest
{
[CompilerGenerated]
protected PropertyChangedEventHandler m_PropertyChanged { get; set; }
public event PropertyChangedEventHandler PropertyChanged
{
[CompilerGenerated]
add
{
m_PropertyChanged += value;
}
[CompilerGenerated]
remove
{
m_PropertyChanged -= value;
}
}
public virtual void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
m_PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public virtual void AddPropertyChanged()
{
PropertyChanged += new PropertyChangedEventHandler(IDimTest_PropertyChanged);
}
private void IDimTest_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
}
} Be warned, that if two events are added at once, one of them may be lost. |
Beta Was this translation helpful? Give feedback.
-
This is by design. Your event is abstract. As such it has no backing field or implementation. There is no value for you to invoke. |
Beta Was this translation helpful? Give feedback.
-
Thank you YairHalberstadt and gafter for your initerpretations. |
Beta Was this translation helpful? Give feedback.
-
@TruePluto public event EventHandler MyEvent { add {} remove {} } What would you invoke if this was your implementation? |
Beta Was this translation helpful? Give feedback.
-
When you invoke an event within a class you're actually referencing the field that contains the delegate for the event directly. That field does not (and can not) exist in an interface because interfaces can't contain state. At most an interface can express methods, which the adder and remover accessors are. But the implementing class has to supply its own event field. The only way to achieve what you're looking to do would be to add a method to the interface for raising the event and expect the implementer to provide the state for the event: public interface I {
event EventHandler MyEvent;
protected void OnEvent();
void DoSomething() {
this.OnEvent();
}
}
public class C : I {
public event EventHandler MyEvent;
void I.OnEvent() => MyEvent?.Invoke(this, EventArgs.Empty);
} |
Beta Was this translation helpful? Give feedback.
-
Seem very weird that property is also cannot have backed field in interface but we can do things with property Is this possible ? public interface I {
EventHandler MyEvent { get; }
void DoSomething() {
MyEvent.Invoke();
}
} |
Beta Was this translation helpful? Give feedback.
-
Yes, that code works. The interface can't contain the state for properties either and the implementer must supply that state. But since your property has a This is more akin to the event problem: public interface I {
EventHandler MyEvent { set; }
void DoSomething() {
MyEvent?.Invoke(this, EventArgs.Empty); // error CS0154
}
} |
Beta Was this translation helpful? Give feedback.
-
Thanks all of you.
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I want to test the new feature of C#8. but i found the default interface method cantnot invoke the event
Beta Was this translation helpful? Give feedback.
All reactions