@@ -760,7 +760,153 @@ public readonly void M()
760
760
}
761
761
762
762
[ Fact ]
763
- public void ReadOnlyMethod_AddRemoveEventHandlers ( )
763
+ public void ReadOnlyMethod_EventAssignment ( )
764
+ {
765
+ var csharp = @"
766
+ using System;
767
+
768
+ public struct S
769
+ {
770
+ public readonly void M()
771
+ {
772
+ Console.WriteLine(E is null);
773
+ // should create local copy
774
+ E += () => {}; // warning
775
+ Console.WriteLine(E is null);
776
+ E -= () => {}; // warning
777
+
778
+ // explicit local copy, no warning
779
+ var copy = this;
780
+ copy.E += () => {};
781
+ Console.WriteLine(copy.E is null);
782
+ }
783
+
784
+ public event Action E;
785
+
786
+ static void Main()
787
+ {
788
+ var s = new S();
789
+ s.M();
790
+ }
791
+ }
792
+ " ;
793
+
794
+ var verifier = CompileAndVerify ( csharp , expectedOutput :
795
+ @"True
796
+ True
797
+ False" ) ;
798
+ verifier . VerifyDiagnostics (
799
+ // (10,9): warning CS8656: Call to non-readonly member 'S.E.add' from a 'readonly' member results in an implicit copy of 'this'.
800
+ // E += () => {}; // warning
801
+ Diagnostic ( ErrorCode . WRN_ImplicitCopyInReadOnlyMember , "E" ) . WithArguments ( "S.E.add" , "this" ) . WithLocation ( 10 , 9 ) ,
802
+ // (12,9): warning CS8656: Call to non-readonly member 'S.E.remove' from a 'readonly' member results in an implicit copy of 'this'.
803
+ // E -= () => {}; // warning
804
+ Diagnostic ( ErrorCode . WRN_ImplicitCopyInReadOnlyMember , "E" ) . WithArguments ( "S.E.remove" , "this" ) . WithLocation ( 12 , 9 ) ) ;
805
+ }
806
+
807
+ [ Fact ]
808
+ public void ReadOnlyStruct_EventAssignment ( )
809
+ {
810
+ var csharp = @"
811
+ using System;
812
+
813
+ public struct S
814
+ {
815
+ public void M()
816
+ {
817
+ E += () => {};
818
+ E -= () => {};
819
+ }
820
+
821
+ public event Action E { add {} remove {} }
822
+ }
823
+ " ;
824
+ var comp = CreateCompilation ( csharp ) ;
825
+ comp . VerifyDiagnostics ( ) ;
826
+ }
827
+
828
+ [ Fact ]
829
+ public void ReadOnlyMethod_ReadOnlyEventAssignment ( )
830
+ {
831
+ var csharp = @"
832
+ using System;
833
+
834
+ public struct S
835
+ {
836
+ public readonly void M()
837
+ {
838
+ E += () => {};
839
+ E -= () => {};
840
+ }
841
+
842
+ public readonly event Action E { add {} remove {} }
843
+ }
844
+ " ;
845
+
846
+ var verifier = CreateCompilation ( csharp ) ;
847
+ verifier . VerifyDiagnostics ( ) ;
848
+ }
849
+
850
+ [ Fact ]
851
+ public void ReadOnlyMethod_Field_EventAssignment ( )
852
+ {
853
+ var csharp = @"
854
+ #pragma warning disable 0067
855
+ using System;
856
+
857
+ public struct S2
858
+ {
859
+ public event Action E;
860
+ }
861
+
862
+ public struct S1
863
+ {
864
+ public S2 s2;
865
+
866
+ public readonly void M()
867
+ {
868
+ s2.E += () => {};
869
+ s2.E -= () => {};
870
+ }
871
+ }
872
+ " ;
873
+
874
+ // TODO: should warn in warning wave https://github.com/dotnet/roslyn/issues/33968
875
+ var verifier = CreateCompilation ( csharp ) ;
876
+ verifier . VerifyDiagnostics ( ) ;
877
+ }
878
+
879
+ [ Fact ]
880
+ public void ReadOnlyStruct_Field_EventAssignment ( )
881
+ {
882
+ var csharp = @"
883
+ #pragma warning disable 0067
884
+ using System;
885
+
886
+ public struct S2
887
+ {
888
+ public event Action E;
889
+ }
890
+
891
+ public readonly struct S1
892
+ {
893
+ public readonly S2 s2;
894
+
895
+ public void M()
896
+ {
897
+ s2.E += () => {};
898
+ s2.E -= () => {};
899
+ }
900
+ }
901
+ " ;
902
+
903
+ // TODO: should warn in warning wave https://github.com/dotnet/roslyn/issues/33968
904
+ var verifier = CreateCompilation ( csharp ) ;
905
+ verifier . VerifyDiagnostics ( ) ;
906
+ }
907
+
908
+ [ Fact ]
909
+ public void ReadOnlyMethod_EventAssignment_Error ( )
764
910
{
765
911
var csharp = @"
766
912
using System;
@@ -779,9 +925,14 @@ void handler(EventArgs args) { }
779
925
}
780
926
}
781
927
" ;
782
- // should warn about E += handler in warning wave (see https://github.com/dotnet/roslyn/issues/33968)
783
928
var comp = CreateCompilation ( csharp ) ;
784
929
comp . VerifyDiagnostics (
930
+ // (9,9): warning CS8656: Call to non-readonly member 'S.E.add' from a 'readonly' member results in an implicit copy of 'this'.
931
+ // E += handler;
932
+ Diagnostic ( ErrorCode . WRN_ImplicitCopyInReadOnlyMember , "E" ) . WithArguments ( "S.E.add" , "this" ) . WithLocation ( 9 , 9 ) ,
933
+ // (10,9): warning CS8656: Call to non-readonly member 'S.E.remove' from a 'readonly' member results in an implicit copy of 'this'.
934
+ // E -= handler;
935
+ Diagnostic ( ErrorCode . WRN_ImplicitCopyInReadOnlyMember , "E" ) . WithArguments ( "S.E.remove" , "this" ) . WithLocation ( 10 , 9 ) ,
785
936
// (11,9): error CS1604: Cannot assign to 'E' because it is read-only
786
937
// E = handler;
787
938
Diagnostic ( ErrorCode . ERR_AssgReadonlyLocal , "E" ) . WithArguments ( "E" ) . WithLocation ( 11 , 9 ) ) ;
0 commit comments