Open stakx opened 6 years ago
I just hit this problem after updating some old test code to use the new NSubstitute (4.0), where they also added the check for the specialname
flag.
I thought at first it was maybe just a case F# not behaving like C#, but according to the ECMA-335 "Common Language Infrastructure (CLI) Partitions I to VI " spec:
CLS Rule 29: The methods that implement an event shall be marked SpecialName in the metadata. (§I.8.11.4)
F# does not mark CLI event accessor methods (
add_X
,remove_X
) with thespecialname
IL flag if the event member is abstract.This can be problematic for Reflection-based tools because they might not correctly recognize event accessor methods as such.
Someone stumbled on this a while ago when using the Moq mocking library against a F#-defined interface type. In order to keep up support for F#, Moq had to stop querying
method.IsSpecialName
, which it used to quickly check whether it was worth trying to find a property or event associated withmethod
(a much more expensive operation). Abandoning that check for F# also meant reduced runtime performance for all other (C#) code.I'd like to bring back this performance optimization in Moq. Therefore it would be great if F# could correctly mark all event accessors as such in metadata.
Repro steps
Compile the following code as a console application, run it, and observe its output.
Expected behavior
The program should print
IsSpecialName = true
for all members, i.e. including those of the abstract typesIAbstract1
,IAbstract2
, andAbstract3
.Actual behavior
The program prints
IsSpecialName = true
only for accessor methods in typesConcrete1
andConcrete2
. The accessor methods from the abstract types do not havespecialname
set.Known workarounds
None known to me. (Am I possibly missing the correct way to define a CLI event in an abstract type?)
Related information