From 9df169946c658af2a2a10010a106b06497f2f1ff Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sat, 25 Jul 2026 11:17:33 -0700 Subject: [PATCH] style: use indexed for over arrays/lists and [] initializers Applies the house conventions consistently across this PR's own code rather than leaving them half-applied: BanChannel had Register/Stop converted while Start kept a foreach, and ConnectionFilters was foreach throughout. Converted every foreach over an array or List, and while doing so hoisted the _reporters/_filters static field reads into a local so the loops match the snapshot pattern Report/Retract/ShouldDeny already use. Left as foreach where there is no indexer: the Dictionary walks in Firewall.ExpireEntries, PromotedGuard.Sweep and BuildAlerts, and BuildAlerts' IEnumerable parameter. Dictionary field initializers become [] (it compiles, same lowering). The three remaining new List(capacity) calls keep their form -- a collection expression cannot carry the capacity hint, and all three size the list exactly. Scoped to files this PR authored or moved; pre-existing loops in AdminGump, Main and Utility are left alone. Co-Authored-By: Claude Opus 5 (1M context) --- Projects/Server/Network/Bans/BanChannel.cs | 15 ++++++++----- Projects/Server/Network/ConnectionFilters.cs | 22 ++++++++++++------- Projects/Server/Utilities/IPAddressUtility.cs | 6 +++-- .../UOContent/Misc/Blocklist/BlocklistFile.cs | 4 +++- .../UOContent/Misc/Blocklist/PromotedGuard.cs | 2 +- .../Misc/CrowdSec/CrowdSecReporter.cs | 13 ++++++----- Projects/UOContent/Misc/Firewall/Firewall.cs | 15 ++++++++----- 7 files changed, 48 insertions(+), 29 deletions(-) diff --git a/Projects/Server/Network/Bans/BanChannel.cs b/Projects/Server/Network/Bans/BanChannel.cs index aae3ed016..6d4ead9b1 100644 --- a/Projects/Server/Network/Bans/BanChannel.cs +++ b/Projects/Server/Network/Bans/BanChannel.cs @@ -46,10 +46,10 @@ public static class BanChannel return; } - for (var i = 0; i < _reporters.Length; i++) + var reporters = _reporters; + for (var i = 0; i < reporters.Length; i++) { - var existing = _reporters[i]; - if (existing.Name == reporter.Name) + if (reporters[i].Name == reporter.Name) { return; } @@ -69,8 +69,10 @@ public static class BanChannel public static void Start(CancellationToken token) { - foreach (var reporter in _reporters) + var reporters = _reporters; + for (var i = 0; i < reporters.Length; i++) { + var reporter = reporters[i]; try { reporter.Start(token); @@ -85,9 +87,10 @@ public static class BanChannel public static void Stop() { - for (var i = 0; i < _reporters.Length; i++) + var reporters = _reporters; + for (var i = 0; i < reporters.Length; i++) { - var reporter = _reporters[i]; + var reporter = reporters[i]; try { reporter.Stop(); diff --git a/Projects/Server/Network/ConnectionFilters.cs b/Projects/Server/Network/ConnectionFilters.cs index eebeae912..6d3113d63 100644 --- a/Projects/Server/Network/ConnectionFilters.cs +++ b/Projects/Server/Network/ConnectionFilters.cs @@ -47,9 +47,10 @@ public static class ConnectionFilters return; } - foreach (var existing in _filters) + var filters = _filters; + for (var i = 0; i < filters.Length; i++) { - if (existing.Name == filter.Name) + if (filters[i].Name == filter.Name) { return; } @@ -104,12 +105,13 @@ public static class ConnectionFilters { logger.Error(e, "Connection filter '{Name}' threw on the accept path; unregistering it", filter.Name); - var updated = new List(_filters.Length); - foreach (var existing in _filters) + var filters = _filters; + var updated = new List(filters.Length); + for (var i = 0; i < filters.Length; i++) { - if (!ReferenceEquals(existing, filter)) + if (!ReferenceEquals(filters[i], filter)) { - updated.Add(existing); + updated.Add(filters[i]); } } @@ -118,8 +120,10 @@ public static class ConnectionFilters public static void Start(CancellationToken token) { - foreach (var filter in _filters) + var filters = _filters; + for (var i = 0; i < filters.Length; i++) { + var filter = filters[i]; try { filter.Start(token); @@ -134,8 +138,10 @@ public static class ConnectionFilters public static void Stop() { - foreach (var filter in _filters) + var filters = _filters; + for (var i = 0; i < filters.Length; i++) { + var filter = filters[i]; try { filter.Stop(); diff --git a/Projects/Server/Utilities/IPAddressUtility.cs b/Projects/Server/Utilities/IPAddressUtility.cs index 245bd2b46..12f81e516 100644 --- a/Projects/Server/Utilities/IPAddressUtility.cs +++ b/Projects/Server/Utilities/IPAddressUtility.cs @@ -152,8 +152,9 @@ public static class IPAddressUtility v = 0; uint acc = 0; int octet = 0, digits = 0, dots = 0; - foreach (var c in s) + for (var i = 0; i < s.Length; i++) { + var c = s[i]; if (c == '.') { if (digits == 0 || octet > 255) @@ -199,8 +200,9 @@ public static class IPAddressUtility v = 0; uint acc = 0; int octet = 0, digits = 0, dots = 0; - foreach (var c in s) + for (var i = 0; i < s.Length; i++) { + var c = s[i]; if (c == (byte)'.') { if (digits == 0 || octet > 255) diff --git a/Projects/UOContent/Misc/Blocklist/BlocklistFile.cs b/Projects/UOContent/Misc/Blocklist/BlocklistFile.cs index 882102bce..a593a7035 100644 --- a/Projects/UOContent/Misc/Blocklist/BlocklistFile.cs +++ b/Projects/UOContent/Misc/Blocklist/BlocklistFile.cs @@ -43,8 +43,10 @@ public static class BlocklistFile var count = 0; if (first.StartsWith('#')) { - foreach (var tok in first.Split(' ', StringSplitOptions.RemoveEmptyEntries)) + var tokens = first.Split(' ', StringSplitOptions.RemoveEmptyEntries); + for (var i = 0; i < tokens.Length; i++) { + var tok = tokens[i]; if (tok.StartsWith("generated=", StringComparison.Ordinal)) { generated = tok["generated=".Length..]; diff --git a/Projects/UOContent/Misc/Blocklist/PromotedGuard.cs b/Projects/UOContent/Misc/Blocklist/PromotedGuard.cs index dea8f038d..4f820b16e 100644 --- a/Projects/UOContent/Misc/Blocklist/PromotedGuard.cs +++ b/Projects/UOContent/Misc/Blocklist/PromotedGuard.cs @@ -21,7 +21,7 @@ namespace Server.Network.Bans; /// Suppresses re-reporting the same IP within a TTL. Accept-path thread only. public sealed class PromotedGuard { - private readonly Dictionary _expiry = new(); + private readonly Dictionary _expiry = []; public bool TryMark(UInt128 ip, long nowTicks, long ttlMs) { diff --git a/Projects/UOContent/Misc/CrowdSec/CrowdSecReporter.cs b/Projects/UOContent/Misc/CrowdSec/CrowdSecReporter.cs index 77334f02f..e09713241 100644 --- a/Projects/UOContent/Misc/CrowdSec/CrowdSecReporter.cs +++ b/Projects/UOContent/Misc/CrowdSec/CrowdSecReporter.cs @@ -213,25 +213,26 @@ public sealed class CrowdSecReporter : IBanReporter } HashSet seen = []; - foreach (var retract in retracts) + for (var i = 0; i < retracts.Count; i++) { if (flushCts.IsCancellationRequested) { break; // out of budget; the rest self-heal via ManualBanDuration } - if (!seen.Add(retract.Ip.ToString())) + var ip = retracts[i].Ip; + if (!seen.Add(ip.ToString())) { continue; } try { - await _client.DeleteDecisionsAsync(_settings.Origin, retract.Ip, flushCts.Token).ConfigureAwait(false); + await _client.DeleteDecisionsAsync(_settings.Origin, ip, flushCts.Token).ConfigureAwait(false); } catch (Exception e) { - logger.Warning(e, "CrowdSec flush-on-stop retract failed for {Address}", retract.Ip); + logger.Warning(e, "CrowdSec flush-on-stop retract failed for {Address}", ip); RecordSendFailure(1); } } @@ -300,9 +301,9 @@ public sealed class CrowdSecReporter : IBanReporter } } - foreach (var retract in retracts) + for (var i = 0; i < retracts.Count; i++) { - var ip = retract.Ip; + var ip = retracts[i].Ip; if (!await SendWithBoundedRetryAsync(() => _client.DeleteDecisionsAsync(_settings.Origin, ip, token), token) .ConfigureAwait(false)) { diff --git a/Projects/UOContent/Misc/Firewall/Firewall.cs b/Projects/UOContent/Misc/Firewall/Firewall.cs index fcb90f5d1..9636dedcf 100644 --- a/Projects/UOContent/Misc/Firewall/Firewall.cs +++ b/Projects/UOContent/Misc/Firewall/Firewall.cs @@ -35,7 +35,7 @@ public static class Firewall private static readonly List _entries = []; // Entries with a TTL: entry -> absolute expiry tick (Core.TickCount). Permanent entries are absent. - private static readonly Dictionary _expiring = new(); + private static readonly Dictionary _expiring = []; private static SortedRangeIndex _index = SortedRangeIndex.Empty; private static bool _indexDirty; @@ -72,8 +72,9 @@ public static class Firewall } using var ranges = PooledRefList.Range>.Create(_entries.Count, mt: false); - foreach (var entry in _entries) + for (var i = 0; i < _entries.Count; i++) { + var entry = _entries[i]; ranges.Add(new SortedRangeIndex.Range(entry.MinIpAddress, entry.MaxIpAddress)); } @@ -174,8 +175,9 @@ public static class Firewall return; } - foreach (var entry in expired) + for (var i = 0; i < expired.Count; i++) { + var entry = expired[i]; _entries.Remove(entry); _expiring.Remove(entry); } @@ -278,8 +280,10 @@ public static class Firewall } var now = DateTime.UtcNow; - foreach (var record in settings.Entries) + var records = settings.Entries; + for (var i = 0; i < records.Length; i++) { + var record = records[i]; var entry = ToFirewallEntry(record.Value); if (entry == null) { @@ -307,8 +311,9 @@ public static class Firewall var nowTicks = Core.TickCount; var list = new List(_entries.Count); - foreach (var entry in _entries) + for (var i = 0; i < _entries.Count; i++) { + var entry = _entries[i]; DateTime? expires = null; if (_expiring.TryGetValue(entry, out var expiresAtTick)) {