@@ -117,7 +117,51 @@ The attribute creates a **requirement** that flows backward from the reflection
117117
118118### It's a contract, not a hint
119119
120- This is crucial to understand: ` DynamicallyAccessedMembers ` isn't just documentation. The trimmer enforces this contract:
120+ This is crucial to understand: ` DynamicallyAccessedMembers ` isn't just documentation. The trimmer enforces this contract.
121+
122+ #### Analogy with generic type constraints
123+
124+ If you're familiar with generic type constraints, ` DynamicallyAccessedMembers ` works similarly. Just as generic constraints flow through your code:
125+
126+ ``` csharp
127+ void Process <T >(T value ) where T : IDisposable
128+ {
129+ value .Dispose (); // OK because constraint guarantees IDisposable
130+ }
131+
132+ void CallProcess <T >(T value ) where T : IDisposable
133+ {
134+ Process (value ); // OK - constraint satisfied
135+ }
136+
137+ void CallProcessBroken <T >(T value )
138+ {
139+ Process (value ); // ERROR - T doesn't have IDisposable constraint
140+ }
141+ ```
142+
143+ ` DynamicallyAccessedMembers ` creates similar requirements that flow through your code:
144+
145+ ``` csharp
146+ void UseReflection ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes .PublicMethods )] Type type )
147+ {
148+ type .GetMethods (); // OK because annotation guarantees methods are preserved
149+ }
150+
151+ void PassType ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes .PublicMethods )] Type type )
152+ {
153+ UseReflection (type ); // OK - requirement satisfied
154+ }
155+
156+ void PassTypeBroken (Type type )
157+ {
158+ UseReflection (type ); // WARNING - type doesn't have required annotation
159+ }
160+ ```
161+
162+ Both create contracts that must be fulfilled, and both produce errors or warnings when the contract can't be satisfied.
163+
164+ #### How the contract is enforced
121165
122166``` csharp
123167[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes .PublicMethods )]
0 commit comments