@@ -104,6 +104,11 @@ public static class LogicalTree
104
104
where T : notnull , FrameworkElement
105
105
where TPredicate : struct , IPredicate < T >
106
106
{
107
+ // Jump label to manually optimize the tail recursive paths for elements with a single
108
+ // child by just overwriting the current element and jumping back to the start of the
109
+ // method. This avoids a recursive call and one stack frame every time.
110
+ Start :
111
+
107
112
if ( element is Panel panel )
108
113
{
109
114
foreach ( UIElement child in panel . Children )
@@ -157,7 +162,9 @@ public static class LogicalTree
157
162
158
163
if ( userControl . Content is FrameworkElement content )
159
164
{
160
- return FindChild < T , TPredicate > ( content , ref predicate ) ;
165
+ element = content ;
166
+
167
+ goto Start ;
161
168
}
162
169
}
163
170
else if ( element is ContentControl contentControl )
@@ -169,7 +176,9 @@ public static class LogicalTree
169
176
170
177
if ( contentControl . Content is FrameworkElement content )
171
178
{
172
- return FindChild < T , TPredicate > ( content , ref predicate ) ;
179
+ element = content ;
180
+
181
+ goto Start ;
173
182
}
174
183
}
175
184
else if ( element is Border border )
@@ -181,7 +190,9 @@ public static class LogicalTree
181
190
182
191
if ( border . Child is FrameworkElement child )
183
192
{
184
- return FindChild < T , TPredicate > ( child , ref predicate ) ;
193
+ element = child ;
194
+
195
+ goto Start ;
185
196
}
186
197
}
187
198
else if ( element . GetContentControl ( ) is FrameworkElement containedControl )
@@ -191,7 +202,9 @@ public static class LogicalTree
191
202
return result ;
192
203
}
193
204
194
- return FindChild < T , TPredicate > ( containedControl , ref predicate ) ;
205
+ element = containedControl ;
206
+
207
+ goto Start ;
195
208
}
196
209
197
210
return null ;
@@ -299,6 +312,8 @@ public static class LogicalTree
299
312
/// <returns>All the child <see cref="FrameworkElement"/> instance from <paramref name="element"/>.</returns>
300
313
public static IEnumerable < FrameworkElement > FindChildren ( this FrameworkElement element )
301
314
{
315
+ Start :
316
+
302
317
if ( element is Panel panel )
303
318
{
304
319
foreach ( UIElement child in panel . Children )
@@ -339,10 +354,9 @@ public static IEnumerable<FrameworkElement> FindChildren(this FrameworkElement e
339
354
{
340
355
yield return content ;
341
356
342
- foreach ( FrameworkElement childOfContent in FindChildren ( content ) )
343
- {
344
- yield return childOfContent ;
345
- }
357
+ element = content ;
358
+
359
+ goto Start ;
346
360
}
347
361
}
348
362
else if ( element is ContentControl contentControl )
@@ -351,10 +365,9 @@ public static IEnumerable<FrameworkElement> FindChildren(this FrameworkElement e
351
365
{
352
366
yield return content ;
353
367
354
- foreach ( FrameworkElement childOfContent in FindChildren ( content ) )
355
- {
356
- yield return childOfContent ;
357
- }
368
+ element = content ;
369
+
370
+ goto Start ;
358
371
}
359
372
}
360
373
else if ( element is Border border )
@@ -363,20 +376,18 @@ public static IEnumerable<FrameworkElement> FindChildren(this FrameworkElement e
363
376
{
364
377
yield return child ;
365
378
366
- foreach ( FrameworkElement childOfChild in FindChildren ( child ) )
367
- {
368
- yield return childOfChild ;
369
- }
379
+ element = child ;
380
+
381
+ goto Start ;
370
382
}
371
383
}
372
384
else if ( element . GetContentControl ( ) is FrameworkElement containedControl )
373
385
{
374
386
yield return containedControl ;
375
387
376
- foreach ( FrameworkElement childOfChild in FindChildren ( containedControl ) )
377
- {
378
- yield return childOfChild ;
379
- }
388
+ element = containedControl ;
389
+
390
+ goto Start ;
380
391
}
381
392
}
382
393
0 commit comments