public override bool Matches(IEnumerable actual, IMatchDiagnostics diagnostics)
        {
            if (actual == null)
            {
                diagnostics.MisMatched(Description.With().Value("items are null").Value("expected", "not null"));
                return(false);
            }
            var items   = AsEfficientList(actual);
            var matcher = new MatchContext(m_matchers);

            if (!matcher.CanStillMatch())
            {
                //no matchers so all ok
                return(true);
            }
            matcher.NextMatcher();
            Object lastMatchedItem    = default(T);
            int    lastMatchedItemIdx = -1;

            for (int i = 0; i < items.Count && matcher.CanStillMatch(); i++)
            {
                var item = items[i];
                if (matcher.Matches(item, i, diagnostics))
                {
                    lastMatchedItem    = item;
                    lastMatchedItemIdx = i;
                    matcher.NextMatcher();
                }
            }
            //check all matchers matched
            if (matcher.CanStillMatch())
            {
                matcher.AddMisMatchMessage(diagnostics, lastMatchedItem, lastMatchedItemIdx, items);
                return(false);
            }
            return(true);
        }
        public override bool Matches(IEnumerable actual, IMatchDiagnostics diagnostics)
        {
            if (actual == null)
            {
                diagnostics.MisMatched("items are null");
                return(false);
            }
            var list   = AsEfficientList(actual);
            var passed = true;
            var ctxt   = new MatchContext(m_matchers);
            int pos    = 0;

            for (; pos < list.Count; pos++)
            {
                var item        = list[pos];
                var matchPassed = false;
                if (ctxt.MatchersRemain())
                {
                    if (m_failOnAdditionalItems)
                    {
                        matchPassed = ctxt.Matches(item, pos, diagnostics);
                    }
                    else
                    {
                        //prevent useless diagnostics messages appearing in output as we call the matchers
                        //repeatably as we try to find a match
                        var childDiag = diagnostics.NewChild();
                        matchPassed = ctxt.Matches(item, pos, childDiag);
                        if (matchPassed)
                        {
                            diagnostics.Value(childDiag);
                        }
                    }
                }

                if (!matchPassed)
                {
                    if (m_failOnAdditionalItems)
                    {
                        passed = false;
                    }
                }
                if (!passed)
                {
                    var child = diagnostics.NewChild();
                    child.Value("position", pos);
                    child.Value("item", item);
                    diagnostics.MisMatched(child);
                    break;
                }
            }
            if (ctxt.MatchersRemain())
            {
                passed = false;
            }
            if (!passed)
            {
                if (!ctxt.MatchersRemain())
                {
                    diagnostics.Text("All matchers matched");
                }
                ctxt.AddMisMatchMessage(diagnostics);
                if (pos < list.Count)
                {
                    diagnostics.Child("Additional items not matched", SubSet(pos, list));
                }
            }
            return(passed);
        }