Proposal: Events as Values #139
Replies: 9 comments
-
I do think some form of first-class support for events should be in C#, but:
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
In that case, the interface could still be part of the standard library, even if there was no special support for implementing it in the language. (And the implementation of that interface would be done by the code generator.)
That depends on how exactly will code generation end up looking. But I think at least something like this should be possible (if not something even better): [EventClass(typeof(DataSource), nameof(DataSource.DataReceived))]
class DataSource_DataReceivedEvent {}
…
new DataSource_DataReceivedEvent(dataSource).Subscribe(OnDataReceived); This proposal is definitely prettier and more convenient than the above code, but maybe the above would be good enough?
In that there is currently no keyword in C# that generates a class implementing some interface and returns an instance of that class. Obviously every language proposal is about adding something new to the language, but I think that preferably, it should be done in a way that fits with the rest of the language, and I'm not sure this approach does. Maybe something that already exists in C#/.Net could be expanded and improved for this purpose ( But this is more of a vague complaint or a gut feeling, not a concrete complaint. |
Beta Was this translation helpful? Give feedback.
-
I wouldn't call it "first-class support for events"..
Also, every time you use delegates/lambdas (especially with closures), a class is generated & instantiated:
The compiler will generate a class to hold |
Beta Was this translation helpful? Give feedback.
-
This idea sort of feels like what we have now with |
Beta Was this translation helpful? Give feedback.
-
A similar proposal was made by Thomas Levesque here: https://github.com/dotnet/roslyn/issues/298 I’m also convinced that there needs to be an (easier) way to pass events as method arguments. It makes Rx, sometimes described as Linq for events, less appealing as it could be. For example if you want to subscribe an event and filter it, you have to write horrible long code:
This could then be reduced with the proposal of Thomas to something like this:
Both Thomas’
Then “Linq for events” will become as comfortable as Linq for objects is since a long time. |
Beta Was this translation helpful? Give feedback.
-
I like it, conceptually. It also has the benefit of reusing an interface that has existed in the BCL for the last seven years, so no runtime changes are required. I do have the following concerns:
|
Beta Was this translation helpful? Give feedback.
-
@quinmars @HaloFour
To work at the language level, the feature must support the core language capabilities, not just a specific pattern (e.g. |
Beta Was this translation helpful? Give feedback.
-
Here is how thought the compiler could do the conversion:
would obviously turn into
into
is a little bit problematic. The natrual solution would be Unfortunately, there are, however, some possible delegate types that wouldn't work, for example:
So it seems that my idea is not general applicable.
It would also help with TPL programming, because events would become awaitable:
I cannot follow all your points, but I also don't think anymore that my idea is generally applicateably (see above). But still I'd prefer the |
Beta Was this translation helpful? Give feedback.
-
Motivation
In FRP, FP, RX, etc. styles of programming, it's desirable to treat events as values, being passable as args, returned, held in variables, etc.
Currently there's no built-in way to do it, and various custom solutions have been developed by the community, relying on code generation, reflection, etc.
Proposal
I propose the following additions to the language & standard library, to enable this goal:
event
keyword, to allow instantiating event expressionsThe interface will look like this:
Usage example:
Implementation
In the above example, the compiler will generate a class implementing
IEvent<Action<string>>
that has a field of typeDataSource
to hold thedataSource
instance.The expression
event(dataSource.DataReceived)
is translated to an instantiation of this generated class. CallingSubscribe
/Unsubscribe
simply forwards the operations to the event.Example implementation:
Further notes
Beta Was this translation helpful? Give feedback.
All reactions