feat(subscriptions): update event subscription handling to use non-nullable source parameters; remove defensive null checks

This commit is contained in:
Miha Kralj
2025-12-26 13:34:21 -08:00
parent 47488985e1
commit 618837dc27
12 changed files with 14 additions and 24 deletions
+1
View File
@@ -81,6 +81,7 @@ Directory: `lib/[category]/[name]/` (e.g., `lib/trends/sma/`)
* Validate all parameters (throw `ArgumentException` for invalid values). * Validate all parameters (throw `ArgumentException` for invalid values).
* Initialize `Name` property (e.g., `$"Sma({period})"`); * Initialize `Name` property (e.g., `$"Sma({period})"`);
* Support chaining: `public [Name](ITValuePublisher source, ...)` * Support chaining: `public [Name](ITValuePublisher source, ...)`
* **Event Subscription:** Subscribe to events directly (`source.Pub += ...`) when the source is passed as a non-nullable parameter. Do not use defensive null checks (`if (_source != null)`).
### The `Update` Method Contract ### The `Update` Method Contract
+1 -1
View File
@@ -551,7 +551,7 @@ public static class SimdExtensions
vSum3 = Avx512F.Add(vSum3, vSum4); vSum3 = Avx512F.Add(vSum3, vSum4);
vSum = Avx512F.Add(vSum, vSum3); vSum = Avx512F.Add(vSum, vSum3);
Vector256<double> v256 = Avx512F.Add(vSum.GetLower(), vSum.GetUpper()); Vector256<double> v256 = Avx.Add(vSum.GetLower(), vSum.GetUpper());
Vector128<double> lower = v256.GetLower(); Vector128<double> lower = v256.GetLower();
Vector128<double> upper = v256.GetUpper(); Vector128<double> upper = v256.GetUpper();
Vector128<double> combined = Sse2.Add(lower, upper); Vector128<double> combined = Sse2.Add(lower, upper);
+2 -2
View File
@@ -69,7 +69,7 @@ public sealed class Bessel : AbstractBase, IDisposable
{ {
_publisher = source; _publisher = source;
_handler = item => Update(item); _handler = item => Update(item);
_publisher.Pub += _handler; source.Pub += _handler;
} }
/// <summary> /// <summary>
@@ -85,7 +85,7 @@ public sealed class Bessel : AbstractBase, IDisposable
_publisher = source; _publisher = source;
_handler = item => Update(item); _handler = item => Update(item);
_publisher.Pub += _handler; source.Pub += _handler;
} }
public override bool IsHot => _state.IsHot; public override bool IsHot => _state.IsHot;
+1 -2
View File
@@ -25,8 +25,7 @@ public class BlmaTests
[Fact] [Fact]
public void Constructor_ValidatesSource() public void Constructor_ValidatesSource()
{ {
Assert.Throws<ArgumentNullException>(() => new Blma(null!, 10)); Assert.Throws<NullReferenceException>(() => new Blma(null!, 10));
Assert.Throws<ArgumentException>(() => new Blma(new object(), 10));
} }
[Fact] [Fact]
+3 -12
View File
@@ -33,19 +33,10 @@ public sealed class Blma : AbstractBase, IDisposable
_weightSum = CalculateWeights(period, _weights); _weightSum = CalculateWeights(period, _weights);
} }
public Blma(object source, int period) : this(period) public Blma(ITValuePublisher source, int period) : this(period)
{ {
ArgumentNullException.ThrowIfNull(source); _publisher = source;
source.Pub += Handle;
if (source is ITValuePublisher pub)
{
_publisher = pub;
_publisher.Pub += Handle;
}
else
{
throw new ArgumentException("Source must implement ITValuePublisher", nameof(source));
}
} }
public void Dispose() public void Dispose()
+1 -1
View File
@@ -58,7 +58,7 @@ public sealed class Dema : AbstractBase, IDisposable
{ {
_publisher = source; _publisher = source;
_listener = (item) => Update(item); _listener = (item) => Update(item);
_publisher.Pub += _listener; source.Pub += _listener;
} }
public Dema(double alpha) public Dema(double alpha)
+1 -1
View File
@@ -8,7 +8,7 @@ public class PwmaTests
{ {
Assert.Throws<ArgumentException>(() => new Pwma(0)); Assert.Throws<ArgumentException>(() => new Pwma(0));
Assert.Throws<ArgumentException>(() => new Pwma(-1)); Assert.Throws<ArgumentException>(() => new Pwma(-1));
Assert.Throws<ArgumentNullException>(() => new Pwma(null!, 10)); Assert.Throws<NullReferenceException>(() => new Pwma(null!, 10));
var pwma = new Pwma(10); var pwma = new Pwma(10);
Assert.NotNull(pwma); Assert.NotNull(pwma);
-1
View File
@@ -56,7 +56,6 @@ public sealed class Pwma : AbstractBase
public Pwma(ITValuePublisher source, int period) : this(period) public Pwma(ITValuePublisher source, int period) : this(period)
{ {
if (source == null) throw new ArgumentNullException(nameof(source));
source.Pub += (item) => Update(item); source.Pub += (item) => Update(item);
} }
+1 -1
View File
@@ -81,7 +81,7 @@ public sealed class T3 : AbstractBase, IDisposable
{ {
_publisher = source; _publisher = source;
_handler = (item) => Update(item); _handler = (item) => Update(item);
_publisher.Pub += _handler; source.Pub += _handler;
} }
/// <summary> /// <summary>
+1 -1
View File
@@ -52,7 +52,7 @@ public sealed class Trima : AbstractBase, IDisposable
public Trima(ITValuePublisher source, int period) : this(period) public Trima(ITValuePublisher source, int period) : this(period)
{ {
_publisher = source; _publisher = source;
_publisher.Pub += _updateHandler; source.Pub += _updateHandler;
} }
public void Dispose() public void Dispose()
+1 -1
View File
@@ -60,7 +60,7 @@ public sealed class Vidya : AbstractBase, IDisposable
{ {
_source = source; _source = source;
_pubHandler = (item) => Update(item); _pubHandler = (item) => Update(item);
_source.Pub += _pubHandler; source.Pub += _pubHandler;
} }
public void Dispose() public void Dispose()
+1 -1
View File
@@ -69,7 +69,7 @@ public sealed class Wma : AbstractBase, IDisposable
{ {
_source = source; _source = source;
_handler = (item) => Update(item); _handler = (item) => Update(item);
_source.Pub += _handler; source.Pub += _handler;
} }
public void Dispose() public void Dispose()