diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt index fd9b8aa05bd..aec4deec22d 100644 --- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt +++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt @@ -1769,11 +1769,11 @@ namespace Akka.Actor.Internal public abstract class ChildrenContainerBase : Akka.Actor.Internal.IChildrenContainer { protected ChildrenContainerBase(System.Collections.Immutable.IImmutableDictionary children) { } - public System.Collections.Generic.IReadOnlyList Children { get; } + public System.Collections.Generic.IReadOnlyCollection Children { get; } protected System.Collections.Immutable.IImmutableDictionary InternalChildren { get; } public virtual bool IsNormal { get; } public virtual bool IsTerminating { get; } - public System.Collections.Generic.IReadOnlyList Stats { get; } + public System.Collections.Generic.IReadOnlyCollection Stats { get; } public abstract Akka.Actor.Internal.IChildrenContainer Add(string name, Akka.Actor.Internal.ChildRestartStats stats); protected void ChildStatsAppender(System.Text.StringBuilder sb, System.Collections.Generic.KeyValuePair kvp, int index) { } public bool Contains(Akka.Actor.IActorRef actor) { } @@ -1796,11 +1796,11 @@ namespace Akka.Actor.Internal public class EmptyChildrenContainer : Akka.Actor.Internal.IChildrenContainer { protected EmptyChildrenContainer() { } - public System.Collections.Generic.IReadOnlyList Children { get; } + public System.Collections.Generic.IReadOnlyCollection Children { get; } public static Akka.Actor.Internal.IChildrenContainer Instance { get; } public virtual bool IsNormal { get; } public virtual bool IsTerminating { get; } - public System.Collections.Generic.IReadOnlyList Stats { get; } + public System.Collections.Generic.IReadOnlyCollection Stats { get; } public virtual Akka.Actor.Internal.IChildrenContainer Add(string name, Akka.Actor.Internal.ChildRestartStats stats) { } public bool Contains(Akka.Actor.IActorRef actor) { } public Akka.Actor.Internal.IChildrenContainer Remove(Akka.Actor.IActorRef child) { } @@ -1813,10 +1813,10 @@ namespace Akka.Actor.Internal } public interface IChildrenContainer { - System.Collections.Generic.IReadOnlyList Children { get; } + System.Collections.Generic.IReadOnlyCollection Children { get; } bool IsNormal { get; } bool IsTerminating { get; } - System.Collections.Generic.IReadOnlyList Stats { get; } + System.Collections.Generic.IReadOnlyCollection Stats { get; } Akka.Actor.Internal.IChildrenContainer Add(string name, Akka.Actor.Internal.ChildRestartStats stats); bool Contains(Akka.Actor.IActorRef actor); Akka.Actor.Internal.IChildrenContainer Remove(Akka.Actor.IActorRef child); diff --git a/src/core/Akka/Actor/ChildrenContainer/Internal/ChildrenContainer.cs b/src/core/Akka/Actor/ChildrenContainer/Internal/ChildrenContainer.cs index c5a1c31f9b3..a6bd3859ce0 100644 --- a/src/core/Akka/Actor/ChildrenContainer/Internal/ChildrenContainer.cs +++ b/src/core/Akka/Actor/ChildrenContainer/Internal/ChildrenContainer.cs @@ -15,8 +15,8 @@ public interface IChildrenContainer IChildrenContainer Remove(IActorRef child); bool TryGetByName(string name, out IChildStats stats); bool TryGetByRef(IActorRef actor, out ChildRestartStats stats); - IReadOnlyList Children { get; } - IReadOnlyList Stats { get; } + IReadOnlyCollection Children { get; } + IReadOnlyCollection Stats { get; } IChildrenContainer ShallDie(IActorRef actor); IChildrenContainer Reserve(string name); IChildrenContainer Unreserve(string name); diff --git a/src/core/Akka/Actor/ChildrenContainer/Internal/ChildrenContainerBase.cs b/src/core/Akka/Actor/ChildrenContainer/Internal/ChildrenContainerBase.cs index e51eaf74749..c0e629b5b8a 100644 --- a/src/core/Akka/Actor/ChildrenContainer/Internal/ChildrenContainerBase.cs +++ b/src/core/Akka/Actor/ChildrenContainer/Internal/ChildrenContainerBase.cs @@ -5,6 +5,7 @@ // //----------------------------------------------------------------------- +using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -15,6 +16,41 @@ namespace Akka.Actor.Internal { public abstract class ChildrenContainerBase : IChildrenContainer { + private class LazyReadOnlyCollection : IReadOnlyCollection + { + private readonly IEnumerable _enumerable; + private int _lazyCount; + + public int Count + { + get + { + int count = _lazyCount; + + if (count == -1) + _lazyCount = count = _enumerable.Count(); + + return count; + } + } + + public LazyReadOnlyCollection(IEnumerable enumerable) + { + _enumerable = enumerable; + _lazyCount = -1; + } + + public IEnumerator GetEnumerator() + { + return _enumerable.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + private readonly IImmutableDictionary _children; protected ChildrenContainerBase(IImmutableDictionary children) @@ -30,25 +66,26 @@ protected ChildrenContainerBase(IImmutableDictionary childr public abstract IChildrenContainer ShallDie(IActorRef actor); public abstract IChildrenContainer Unreserve(string name); - public IReadOnlyList Children + public IReadOnlyCollection Children { get { - return (from stat in InternalChildren.Values - let childRestartStats = stat as ChildRestartStats - where childRestartStats != null - select childRestartStats.Child).ToList(); + var children = InternalChildren.Values + .OfType() + .Select(item => item.Child); + + // The children collection must stay lazy evaluated + return new LazyReadOnlyCollection(children); } } - public IReadOnlyList Stats + public IReadOnlyCollection Stats { get { - return (from stat in InternalChildren.Values - let childRestartStats = stat as ChildRestartStats - where childRestartStats != null - select childRestartStats).ToList(); + var children = InternalChildren.Values.OfType(); + + return new LazyReadOnlyCollection(children); } } diff --git a/src/core/Akka/Actor/ChildrenContainer/Internal/EmptyChildrenContainer.cs b/src/core/Akka/Actor/ChildrenContainer/Internal/EmptyChildrenContainer.cs index 7317cc2ce8c..91f4adf7526 100644 --- a/src/core/Akka/Actor/ChildrenContainer/Internal/EmptyChildrenContainer.cs +++ b/src/core/Akka/Actor/ChildrenContainer/Internal/EmptyChildrenContainer.cs @@ -54,9 +54,9 @@ public bool Contains(IActorRef actor) return false; } - public IReadOnlyList Children { get { return ImmutableList.Empty; } } + public IReadOnlyCollection Children { get { return ImmutableList.Empty; } } - public IReadOnlyList Stats { get { return ImmutableList.Empty; } } + public IReadOnlyCollection Stats { get { return ImmutableList.Empty; } } public IChildrenContainer ShallDie(IActorRef actor) {