@@ -104,6 +104,11 @@ public static class LogicalTree
104104 where T : notnull , FrameworkElement
105105 where TPredicate : struct , IPredicate < T >
106106 {
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+
107112 if ( element is Panel panel )
108113 {
109114 foreach ( UIElement child in panel . Children )
@@ -157,7 +162,9 @@ public static class LogicalTree
157162
158163 if ( userControl . Content is FrameworkElement content )
159164 {
160- return FindChild < T , TPredicate > ( content , ref predicate ) ;
165+ element = content ;
166+
167+ goto Start ;
161168 }
162169 }
163170 else if ( element is ContentControl contentControl )
@@ -169,7 +176,9 @@ public static class LogicalTree
169176
170177 if ( contentControl . Content is FrameworkElement content )
171178 {
172- return FindChild < T , TPredicate > ( content , ref predicate ) ;
179+ element = content ;
180+
181+ goto Start ;
173182 }
174183 }
175184 else if ( element is Border border )
@@ -181,7 +190,9 @@ public static class LogicalTree
181190
182191 if ( border . Child is FrameworkElement child )
183192 {
184- return FindChild < T , TPredicate > ( child , ref predicate ) ;
193+ element = child ;
194+
195+ goto Start ;
185196 }
186197 }
187198 else if ( element . GetContentControl ( ) is FrameworkElement containedControl )
@@ -191,7 +202,9 @@ public static class LogicalTree
191202 return result ;
192203 }
193204
194- return FindChild < T , TPredicate > ( containedControl , ref predicate ) ;
205+ element = containedControl ;
206+
207+ goto Start ;
195208 }
196209
197210 return null ;
@@ -299,6 +312,8 @@ public static class LogicalTree
299312 /// <returns>All the child <see cref="FrameworkElement"/> instance from <paramref name="element"/>.</returns>
300313 public static IEnumerable < FrameworkElement > FindChildren ( this FrameworkElement element )
301314 {
315+ Start :
316+
302317 if ( element is Panel panel )
303318 {
304319 foreach ( UIElement child in panel . Children )
@@ -339,10 +354,9 @@ public static IEnumerable<FrameworkElement> FindChildren(this FrameworkElement e
339354 {
340355 yield return content ;
341356
342- foreach ( FrameworkElement childOfContent in FindChildren ( content ) )
343- {
344- yield return childOfContent ;
345- }
357+ element = content ;
358+
359+ goto Start ;
346360 }
347361 }
348362 else if ( element is ContentControl contentControl )
@@ -351,10 +365,9 @@ public static IEnumerable<FrameworkElement> FindChildren(this FrameworkElement e
351365 {
352366 yield return content ;
353367
354- foreach ( FrameworkElement childOfContent in FindChildren ( content ) )
355- {
356- yield return childOfContent ;
357- }
368+ element = content ;
369+
370+ goto Start ;
358371 }
359372 }
360373 else if ( element is Border border )
@@ -363,20 +376,18 @@ public static IEnumerable<FrameworkElement> FindChildren(this FrameworkElement e
363376 {
364377 yield return child ;
365378
366- foreach ( FrameworkElement childOfChild in FindChildren ( child ) )
367- {
368- yield return childOfChild ;
369- }
379+ element = child ;
380+
381+ goto Start ;
370382 }
371383 }
372384 else if ( element . GetContentControl ( ) is FrameworkElement containedControl )
373385 {
374386 yield return containedControl ;
375387
376- foreach ( FrameworkElement childOfChild in FindChildren ( containedControl ) )
377- {
378- yield return childOfChild ;
379- }
388+ element = containedControl ;
389+
390+ goto Start ;
380391 }
381392 }
382393
0 commit comments