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<T>(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) <noreply@anthropic.com>
This commit is contained in:
Kamron Batman 2026-07-25 11:17:33 -07:00
parent 0f64d834b4
commit 9df169946c
No known key found for this signature in database
GPG key ID: 7D81DF26D9A5D94A
7 changed files with 48 additions and 29 deletions

View file

@ -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();

View file

@ -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<IConnectionFilter>(_filters.Length);
foreach (var existing in _filters)
var filters = _filters;
var updated = new List<IConnectionFilter>(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();

View file

@ -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)

View file

@ -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..];

View file

@ -21,7 +21,7 @@ namespace Server.Network.Bans;
/// <summary>Suppresses re-reporting the same IP within a TTL. Accept-path thread only.</summary>
public sealed class PromotedGuard
{
private readonly Dictionary<UInt128, long> _expiry = new();
private readonly Dictionary<UInt128, long> _expiry = [];
public bool TryMark(UInt128 ip, long nowTicks, long ttlMs)
{

View file

@ -213,25 +213,26 @@ public sealed class CrowdSecReporter : IBanReporter
}
HashSet<string> 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))
{

View file

@ -35,7 +35,7 @@ public static class Firewall
private static readonly List<IFirewallEntry> _entries = [];
// Entries with a TTL: entry -> absolute expiry tick (Core.TickCount). Permanent entries are absent.
private static readonly Dictionary<IFirewallEntry, long> _expiring = new();
private static readonly Dictionary<IFirewallEntry, long> _expiring = [];
private static SortedRangeIndex<UInt128> _index = SortedRangeIndex<UInt128>.Empty;
private static bool _indexDirty;
@ -72,8 +72,9 @@ public static class Firewall
}
using var ranges = PooledRefList<SortedRangeIndex<UInt128>.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<UInt128>.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<FirewallEntryRecord>(_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))
{