| File: ModelBinding\Validation\ValidationStack.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj (Microsoft.AspNetCore.Mvc.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable enable using System.Diagnostics; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation; #pragma warning disable CA1852 // Seal internal types internal class ValidationStack #pragma warning restore CA1852 // Seal internal types { public int Count => HashSet?.Count ?? List.Count; // We tested the performance of a list at size 15 and found it still better than hashset, but to avoid a costly // O(n) search at larger n we set the cutoff to 20. If someone finds the point where they intersect feel free to change this number. internal const int CutOff = 20; internal List<object> List { get; } = new List<object>(); internal HashSet<object>? HashSet { get; set; } public bool Push(object model) { if (HashSet != null) { return HashSet.Add(model); } if (ListContains(model)) { return false; } List.Add(model); if (HashSet == null && List.Count > CutOff) { HashSet = new HashSet<object>(List, ReferenceEqualityComparer.Instance); } return true; } public void Pop(object? model) { if (HashSet != null) { HashSet.Remove(model!); } else { if (model != null) { Debug.Assert(ReferenceEquals(List[List.Count - 1], model)); List.RemoveAt(List.Count - 1); } } } private bool ListContains(object model) { for (var i = 0; i < List.Count; i++) { if (ReferenceEquals(model, List[i])) { return true; } } return false; } }