@@ -65,18 +65,22 @@ internal static bool CanWrapObject(object obj, Type underlyingType)
6565 return false ;
6666 }
6767
68- ConcurrentDictionary < Type , bool > wrappedObject = SupportedObjectWrappers . GetOrAdd ( underlyingType , _ => new ConcurrentDictionary < Type , bool > ( ) ) ;
69-
7068 // Avoid creating the delegate if the value already exists
71- bool canCast ;
72- if ( ! wrappedObject . TryGetValue ( obj . GetType ( ) , out canCast ) )
69+ if ( ! SupportedObjectWrappers . TryGetValue ( underlyingType , out var wrappedObject ) )
7370 {
74- canCast = wrappedObject . GetOrAdd (
75- obj . GetType ( ) ,
76- kind => underlyingType . GetTypeInfo ( ) . IsAssignableFrom ( obj . GetType ( ) . GetTypeInfo ( ) ) ) ;
71+ wrappedObject = SupportedObjectWrappers . GetOrAdd ( underlyingType , static _ => new ConcurrentDictionary < Type , bool > ( ) ) ;
7772 }
7873
79- return canCast ;
74+ // Avoid creating the delegate and capture class if the value already exists
75+ return wrappedObject . TryGetValue ( obj . GetType ( ) , out var canCast )
76+ ? canCast
77+ : GetOrAdd ( obj , underlyingType , wrappedObject ) ;
78+
79+ // Don't inline this method. Otherwise a capture class is generated on each call to CanWrapObject.
80+ static bool GetOrAdd ( object obj , Type underlyingType , ConcurrentDictionary < Type , bool > wrappedObject )
81+ => wrappedObject . GetOrAdd (
82+ obj . GetType ( ) ,
83+ kind => underlyingType . GetTypeInfo ( ) . IsAssignableFrom ( obj . GetType ( ) . GetTypeInfo ( ) ) ) ;
8084 }
8185
8286 internal static bool CanWrapNode ( SyntaxNode node , Type underlyingType )
@@ -93,18 +97,22 @@ internal static bool CanWrapNode(SyntaxNode node, Type underlyingType)
9397 return false ;
9498 }
9599
96- ConcurrentDictionary < SyntaxKind , bool > wrappedSyntax = SupportedSyntaxWrappers . GetOrAdd ( underlyingType , _ => new ConcurrentDictionary < SyntaxKind , bool > ( ) ) ;
97-
98100 // Avoid creating the delegate if the value already exists
99- bool canCast ;
100- if ( ! wrappedSyntax . TryGetValue ( node . Kind ( ) , out canCast ) )
101+ if ( ! SupportedSyntaxWrappers . TryGetValue ( underlyingType , out var wrappedSyntax ) )
101102 {
102- canCast = wrappedSyntax . GetOrAdd (
103- node . Kind ( ) ,
104- kind => underlyingType . GetTypeInfo ( ) . IsAssignableFrom ( node . GetType ( ) . GetTypeInfo ( ) ) ) ;
103+ wrappedSyntax = SupportedSyntaxWrappers . GetOrAdd ( underlyingType , static _ => new ConcurrentDictionary < SyntaxKind , bool > ( ) ) ;
105104 }
106105
107- return canCast ;
106+ // Avoid creating the delegate and capture class if the value already exists
107+ return wrappedSyntax . TryGetValue ( node . Kind ( ) , out var canCast )
108+ ? canCast
109+ : GetOrAdd ( node , underlyingType , wrappedSyntax ) ;
110+
111+ // Don't inline this method. Otherwise a capture class is generated on each call to CanWrapNode.
112+ static bool GetOrAdd ( SyntaxNode node , Type underlyingType , ConcurrentDictionary < SyntaxKind , bool > wrappedSyntax ) =>
113+ wrappedSyntax . GetOrAdd (
114+ node . Kind ( ) ,
115+ kind => underlyingType . GetTypeInfo ( ) . IsAssignableFrom ( node . GetType ( ) . GetTypeInfo ( ) ) ) ;
108116 }
109117
110118 internal static bool CanWrapOperation ( IOperation operation , Type underlyingType )
@@ -121,18 +129,22 @@ internal static bool CanWrapOperation(IOperation operation, Type underlyingType)
121129 return false ;
122130 }
123131
124- ConcurrentDictionary < OperationKind , bool > wrappedSyntax = SupportedOperationWrappers . GetOrAdd ( underlyingType , _ => new ConcurrentDictionary < OperationKind , bool > ( ) ) ;
125-
126132 // Avoid creating the delegate if the value already exists
127- bool canCast ;
128- if ( ! wrappedSyntax . TryGetValue ( operation . Kind , out canCast ) )
133+ if ( ! SupportedOperationWrappers . TryGetValue ( underlyingType , out var wrappedSyntax ) )
129134 {
130- canCast = wrappedSyntax . GetOrAdd (
131- operation . Kind ,
132- kind => underlyingType . GetTypeInfo ( ) . IsAssignableFrom ( operation . GetType ( ) . GetTypeInfo ( ) ) ) ;
135+ wrappedSyntax = SupportedOperationWrappers . GetOrAdd ( underlyingType , static _ => new ConcurrentDictionary < OperationKind , bool > ( ) ) ;
133136 }
134137
135- return canCast ;
138+ // Avoid creating the delegate if the value already exists
139+ return wrappedSyntax . TryGetValue ( operation . Kind , out var canCast )
140+ ? canCast
141+ : GetOrAdd ( operation , underlyingType , wrappedSyntax ) ;
142+
143+ // Don't inline this method. Otherwise a capture class is generated on each call to CanWrapOperation.
144+ static bool GetOrAdd ( IOperation operation , Type underlyingType , ConcurrentDictionary < OperationKind , bool > wrappedSyntax ) =>
145+ wrappedSyntax . GetOrAdd (
146+ operation . Kind ,
147+ kind => underlyingType . GetTypeInfo ( ) . IsAssignableFrom ( operation . GetType ( ) . GetTypeInfo ( ) ) ) ;
136148 }
137149
138150 internal static Func < TOperation , TProperty > CreateOperationPropertyAccessor < TOperation , TProperty > ( Type type , string propertyName )
0 commit comments