test(core-tests): 收敛函数式与状态测试的低风险 warning

- 补齐 WaitForTask、ResourceManager、State 与 StateMachine 测试中的低风险 ConfigureAwait(false)
- 更新 AsyncKeyLock、ResultExtensions、ResultT 与 Pipe 测试中的 culture 和异步等待写法
This commit is contained in:
gewuyou 2026-04-25 10:08:59 +08:00
parent 737d0b5037
commit b7560fcc08
8 changed files with 68 additions and 64 deletions

View File

@ -25,7 +25,7 @@ public sealed class AsyncKeyLockManagerTests
using var manager = new AsyncKeyLockManager(); using var manager = new AsyncKeyLockManager();
// Act // Act
await using var handle = await manager.AcquireLockAsync("test-key"); await using var handle = await manager.AcquireLockAsync("test-key").ConfigureAwait(false);
// Assert // Assert
Assert.That(handle, Is.Not.Null); Assert.That(handle, Is.Not.Null);
@ -47,13 +47,13 @@ public sealed class AsyncKeyLockManagerTests
var index = i; var index = i;
tasks.Add(Task.Run(async () => tasks.Add(Task.Run(async () =>
{ {
await using var handle = await manager.AcquireLockAsync("same-key"); await using var handle = await manager.AcquireLockAsync("same-key").ConfigureAwait(false);
executionOrder.Add(index); executionOrder.Add(index);
await Task.Delay(10); await Task.Delay(10).ConfigureAwait(false);
})); }));
} }
await Task.WhenAll(tasks); await Task.WhenAll(tasks).ConfigureAwait(false);
// Assert // Assert
Assert.That(executionOrder.Count, Is.EqualTo(5)); Assert.That(executionOrder.Count, Is.EqualTo(5));
@ -75,15 +75,15 @@ public sealed class AsyncKeyLockManagerTests
var key = $"key-{i}"; var key = $"key-{i}";
tasks.Add(Task.Run(async () => tasks.Add(Task.Run(async () =>
{ {
await using var handle = await manager.AcquireLockAsync(key); await using var handle = await manager.AcquireLockAsync(key).ConfigureAwait(false);
var current = Interlocked.Increment(ref concurrentCount); var current = Interlocked.Increment(ref concurrentCount);
maxConcurrent = Math.Max(maxConcurrent, current); maxConcurrent = Math.Max(maxConcurrent, current);
await Task.Delay(50); await Task.Delay(50).ConfigureAwait(false);
Interlocked.Decrement(ref concurrentCount); Interlocked.Decrement(ref concurrentCount);
})); }));
} }
await Task.WhenAll(tasks); await Task.WhenAll(tasks).ConfigureAwait(false);
// Assert // Assert
Assert.That(maxConcurrent, Is.GreaterThan(1)); Assert.That(maxConcurrent, Is.GreaterThan(1));
@ -94,13 +94,13 @@ public sealed class AsyncKeyLockManagerTests
{ {
// Arrange // Arrange
using var manager = new AsyncKeyLockManager(); using var manager = new AsyncKeyLockManager();
var handle = await manager.AcquireLockAsync("test-key"); var handle = await manager.AcquireLockAsync("test-key").ConfigureAwait(false);
// Act // Act
await handle.DisposeAsync(); await handle.DisposeAsync().ConfigureAwait(false);
// Assert - 应该能再次获取锁 // Assert - 应该能再次获取锁
await using var handle2 = await manager.AcquireLockAsync("test-key"); await using var handle2 = await manager.AcquireLockAsync("test-key").ConfigureAwait(false);
Assert.That(handle2, Is.Not.Null); Assert.That(handle2, Is.Not.Null);
} }
@ -117,8 +117,8 @@ public sealed class AsyncKeyLockManagerTests
var key = $"key-{i % 10}"; var key = $"key-{i % 10}";
tasks.Add(Task.Run(async () => tasks.Add(Task.Run(async () =>
{ {
await using var handle = await manager.AcquireLockAsync(key); await using var handle = await manager.AcquireLockAsync(key).ConfigureAwait(false);
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
})); }));
} }
@ -139,14 +139,14 @@ public sealed class AsyncKeyLockManagerTests
{ {
tasks.Add(Task.Run(async () => tasks.Add(Task.Run(async () =>
{ {
await using var handle = await manager.AcquireLockAsync("same-key"); await using var handle = await manager.AcquireLockAsync("same-key").ConfigureAwait(false);
var temp = counter; var temp = counter;
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
counter = temp + 1; counter = temp + 1;
})); }));
} }
await Task.WhenAll(tasks); await Task.WhenAll(tasks).ConfigureAwait(false);
// Assert // Assert
Assert.That(counter, Is.EqualTo(100)); Assert.That(counter, Is.EqualTo(100));
@ -161,13 +161,13 @@ public sealed class AsyncKeyLockManagerTests
lockTimeout: TimeSpan.FromMilliseconds(200)); lockTimeout: TimeSpan.FromMilliseconds(200));
// Act // Act
await using (var handle = await manager.AcquireLockAsync("temp-key")) await using (var handle = await manager.AcquireLockAsync("temp-key").ConfigureAwait(false))
{ {
// 持有锁 // 持有锁
} }
// 等待清理 // 等待清理
await Task.Delay(400); await Task.Delay(400).ConfigureAwait(false);
var stats = manager.GetStatistics(); var stats = manager.GetStatistics();
@ -184,10 +184,10 @@ public sealed class AsyncKeyLockManagerTests
lockTimeout: TimeSpan.FromMilliseconds(200)); lockTimeout: TimeSpan.FromMilliseconds(200));
// Act // Act
await using var handle = await manager.AcquireLockAsync("active-key"); await using var handle = await manager.AcquireLockAsync("active-key").ConfigureAwait(false);
// 等待清理尝试 // 等待清理尝试
await Task.Delay(400); await Task.Delay(400).ConfigureAwait(false);
var activeLocks = manager.GetActiveLocks(); var activeLocks = manager.GetActiveLocks();
@ -202,9 +202,9 @@ public sealed class AsyncKeyLockManagerTests
using var manager = new AsyncKeyLockManager(); using var manager = new AsyncKeyLockManager();
// Act // Act
await using (await manager.AcquireLockAsync("key1")) await using (await manager.AcquireLockAsync("key1").ConfigureAwait(false))
{ {
await using var handle2 = await manager.AcquireLockAsync("key2"); await using var handle2 = await manager.AcquireLockAsync("key2").ConfigureAwait(false);
var stats = manager.GetStatistics(); var stats = manager.GetStatistics();
// Assert // Assert
@ -223,8 +223,8 @@ public sealed class AsyncKeyLockManagerTests
using var manager = new AsyncKeyLockManager(); using var manager = new AsyncKeyLockManager();
// Act // Act
await using var handle1 = await manager.AcquireLockAsync("key1"); await using var handle1 = await manager.AcquireLockAsync("key1").ConfigureAwait(false);
await using var handle2 = await manager.AcquireLockAsync("key2"); await using var handle2 = await manager.AcquireLockAsync("key2").ConfigureAwait(false);
var activeLocks = manager.GetActiveLocks(); var activeLocks = manager.GetActiveLocks();
@ -254,14 +254,14 @@ public sealed class AsyncKeyLockManagerTests
using var cts = new CancellationTokenSource(); using var cts = new CancellationTokenSource();
// 先获取锁 // 先获取锁
await using var handle = await manager.AcquireLockAsync("test-key", cts.Token); await using var handle = await manager.AcquireLockAsync("test-key", cts.Token).ConfigureAwait(false);
// Act // Act
await cts.CancelAsync(); await cts.CancelAsync().ConfigureAwait(false);
// Assert // Assert
Assert.CatchAsync<OperationCanceledException>(async () => Assert.CatchAsync<OperationCanceledException>(async () =>
await manager.AcquireLockAsync("test-key", cts.Token)); await manager.AcquireLockAsync("test-key", cts.Token).ConfigureAwait(false));
} }
[Test] [Test]
@ -295,8 +295,8 @@ public sealed class AsyncKeyLockManagerTests
{ {
for (var j = 0; j < 10; j++) for (var j = 0; j < 10; j++)
{ {
await using var handle = await manager.AcquireLockAsync($"key-{j % 5}"); await using var handle = await manager.AcquireLockAsync($"key-{j % 5}").ConfigureAwait(false);
await Task.Delay(10); await Task.Delay(10).ConfigureAwait(false);
} }
})); }));
} }
@ -324,11 +324,11 @@ public sealed class AsyncKeyLockManagerTests
{ {
// Arrange // Arrange
using var manager = new AsyncKeyLockManager(); using var manager = new AsyncKeyLockManager();
var handle = await manager.AcquireLockAsync("test-key"); var handle = await manager.AcquireLockAsync("test-key").ConfigureAwait(false);
// Act // Act
await handle.DisposeAsync(); await handle.DisposeAsync().ConfigureAwait(false);
await handle.DisposeAsync(); await handle.DisposeAsync().ConfigureAwait(false);
handle.Dispose(); handle.Dispose();
// Assert - 不应该抛出异常 // Assert - 不应该抛出异常

View File

@ -284,13 +284,13 @@ public class WaitForTaskTests
var expectedValue = 123; var expectedValue = 123;
var task = Task.Run(async () => var task = Task.Run(async () =>
{ {
await Task.Delay(50); await Task.Delay(50).ConfigureAwait(false);
return expectedValue; return expectedValue;
}); });
var wait = new WaitForTask<int>(task); var wait = new WaitForTask<int>(task);
await task; await task.ConfigureAwait(false);
Task.Delay(100).Wait(); Task.Delay(100).Wait();
@ -313,4 +313,4 @@ public class WaitForTaskTests
Assert.That(wait.IsDone, Is.True); Assert.That(wait.IsDone, Is.True);
} }
} }

View File

@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
using System.Globalization;
using GFramework.Core.Functional; using GFramework.Core.Functional;
namespace GFramework.Core.Tests.Extensions; namespace GFramework.Core.Tests.Extensions;
@ -122,7 +123,7 @@ public class ResultExtensionsTests
public void Map_Should_Transform_Success_Value() public void Map_Should_Transform_Success_Value()
{ {
var result = Result<int>.Succeed(42); var result = Result<int>.Succeed(42);
var mapped = result.Map(x => x.ToString()); var mapped = result.Map(x => x.ToString(CultureInfo.InvariantCulture));
Assert.That(mapped.IsSuccess, Is.True); Assert.That(mapped.IsSuccess, Is.True);
Assert.That(mapped.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42")); Assert.That(mapped.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42"));
} }
@ -135,7 +136,7 @@ public class ResultExtensionsTests
{ {
var exception = new Exception("Error"); var exception = new Exception("Error");
var result = Result<int>.Fail(exception); var result = Result<int>.Fail(exception);
var mapped = result.Map(x => x.ToString()); var mapped = result.Map(x => x.ToString(CultureInfo.InvariantCulture));
Assert.That(mapped.IsFaulted, Is.True); Assert.That(mapped.IsFaulted, Is.True);
Assert.That(mapped.Exception, Is.SameAs(exception)); Assert.That(mapped.Exception, Is.SameAs(exception));
} }
@ -157,7 +158,7 @@ public class ResultExtensionsTests
public void Bind_Should_Chain_Success_Results() public void Bind_Should_Chain_Success_Results()
{ {
var result = Result<int>.Succeed(42); var result = Result<int>.Succeed(42);
var bound = result.Bind(x => Result<string>.Succeed(x.ToString())); var bound = result.Bind(x => Result<string>.Succeed(x.ToString(CultureInfo.InvariantCulture)));
Assert.That(bound.IsSuccess, Is.True); Assert.That(bound.IsSuccess, Is.True);
Assert.That(bound.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42")); Assert.That(bound.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42"));
} }
@ -170,7 +171,7 @@ public class ResultExtensionsTests
{ {
var exception = new Exception("Error"); var exception = new Exception("Error");
var result = Result<int>.Fail(exception); var result = Result<int>.Fail(exception);
var bound = result.Bind(x => Result<string>.Succeed(x.ToString())); var bound = result.Bind(x => Result<string>.Succeed(x.ToString(CultureInfo.InvariantCulture)));
Assert.That(bound.IsFaulted, Is.True); Assert.That(bound.IsFaulted, Is.True);
Assert.That(bound.Exception, Is.SameAs(exception)); Assert.That(bound.Exception, Is.SameAs(exception));
} }
@ -449,9 +450,9 @@ public class ResultExtensionsTests
{ {
var result = await ResultExtensions.TryAsync(async () => var result = await ResultExtensions.TryAsync(async () =>
{ {
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
return 42; return 42;
}); }).ConfigureAwait(false);
Assert.That(result.IsSuccess, Is.True); Assert.That(result.IsSuccess, Is.True);
Assert.That(result.Match(succ: v => v, fail: _ => 0), Is.EqualTo(42)); Assert.That(result.Match(succ: v => v, fail: _ => 0), Is.EqualTo(42));
} }
@ -464,9 +465,9 @@ public class ResultExtensionsTests
{ {
var result = await ResultExtensions.TryAsync<int>(async () => var result = await ResultExtensions.TryAsync<int>(async () =>
{ {
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
throw new InvalidOperationException("Error"); throw new InvalidOperationException("Error");
}); }).ConfigureAwait(false);
Assert.That(result.IsFaulted, Is.True); Assert.That(result.IsFaulted, Is.True);
Assert.That(result.Exception, Is.TypeOf<InvalidOperationException>()); Assert.That(result.Exception, Is.TypeOf<InvalidOperationException>());
} }
@ -477,7 +478,8 @@ public class ResultExtensionsTests
[Test] [Test]
public async Task TryAsync_Should_Handle_Synchronous_Exceptions() public async Task TryAsync_Should_Handle_Synchronous_Exceptions()
{ {
var result = await ResultExtensions.TryAsync<int>(() => throw new InvalidOperationException("Sync error")); var result = await ResultExtensions.TryAsync<int>(() => throw new InvalidOperationException("Sync error"))
.ConfigureAwait(false);
Assert.That(result.IsFaulted, Is.True); Assert.That(result.IsFaulted, Is.True);
} }

View File

@ -1,3 +1,4 @@
using System.Globalization;
using GFramework.Core.Functional.Pipe; using GFramework.Core.Functional.Pipe;
using NUnit.Framework; using NUnit.Framework;
@ -123,7 +124,7 @@ public class PipeExtensionsTests
var result = value var result = value
.Pipe(x => x * 2) .Pipe(x => x * 2)
.Pipe(x => x + 10) .Pipe(x => x + 10)
.Pipe(x => x.ToString()); .Pipe(x => x.ToString(CultureInfo.InvariantCulture));
// Assert // Assert
Assert.That(result, Is.EqualTo("20")); Assert.That(result, Is.EqualTo("20"));
@ -139,7 +140,7 @@ public class PipeExtensionsTests
var value = 42; var value = 42;
// Act // Act
var result = value.Let(x => x.ToString()); var result = value.Let(x => x.ToString(CultureInfo.InvariantCulture));
// Assert // Assert
Assert.That(result, Is.EqualTo("42")); Assert.That(result, Is.EqualTo("42"));
@ -171,7 +172,7 @@ public class PipeExtensionsTests
var result = value.Let(s => new var result = value.Let(s => new
{ {
Original = s, Original = s,
Upper = s.ToUpper(), Upper = s.ToUpperInvariant(),
Length = s.Length Length = s.Length
}); });
@ -280,4 +281,4 @@ public class PipeExtensionsTests
// Assert // Assert
Assert.That(result, Is.EqualTo("Large: 20")); Assert.That(result, Is.EqualTo("Large: 20"));
} }
} }

View File

@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
using System.Globalization;
using GFramework.Core.Functional; using GFramework.Core.Functional;
using NUnit.Framework; using NUnit.Framework;
@ -314,7 +315,7 @@ public class ResultTTests
public void Map_Should_Transform_Value_When_Success() public void Map_Should_Transform_Value_When_Success()
{ {
var result = Result<int>.Succeed(42); var result = Result<int>.Succeed(42);
var mapped = result.Map(x => x.ToString()); var mapped = result.Map(x => x.ToString(CultureInfo.InvariantCulture));
Assert.That(mapped.IsSuccess, Is.True); Assert.That(mapped.IsSuccess, Is.True);
Assert.That(mapped.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42")); Assert.That(mapped.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42"));
} }
@ -327,7 +328,7 @@ public class ResultTTests
{ {
var exception = new Exception("Error"); var exception = new Exception("Error");
var result = Result<int>.Fail(exception); var result = Result<int>.Fail(exception);
var mapped = result.Map(x => x.ToString()); var mapped = result.Map(x => x.ToString(CultureInfo.InvariantCulture));
Assert.That(mapped.IsFaulted, Is.True); Assert.That(mapped.IsFaulted, Is.True);
Assert.That(mapped.Exception, Is.SameAs(exception)); Assert.That(mapped.Exception, Is.SameAs(exception));
} }
@ -360,7 +361,7 @@ public class ResultTTests
public void Bind_Should_Chain_Success_Results() public void Bind_Should_Chain_Success_Results()
{ {
var result = Result<int>.Succeed(42); var result = Result<int>.Succeed(42);
var bound = result.Bind(x => Result<string>.Succeed(x.ToString())); var bound = result.Bind(x => Result<string>.Succeed(x.ToString(CultureInfo.InvariantCulture)));
Assert.That(bound.IsSuccess, Is.True); Assert.That(bound.IsSuccess, Is.True);
Assert.That(bound.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42")); Assert.That(bound.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42"));
} }
@ -373,7 +374,7 @@ public class ResultTTests
{ {
var exception = new Exception("Error"); var exception = new Exception("Error");
var result = Result<int>.Fail(exception); var result = Result<int>.Fail(exception);
var bound = result.Bind(x => Result<string>.Succeed(x.ToString())); var bound = result.Bind(x => Result<string>.Succeed(x.ToString(CultureInfo.InvariantCulture)));
Assert.That(bound.IsFaulted, Is.True); Assert.That(bound.IsFaulted, Is.True);
Assert.That(bound.Exception, Is.SameAs(exception)); Assert.That(bound.Exception, Is.SameAs(exception));
} }
@ -414,7 +415,7 @@ public class ResultTTests
var mapped = await result.MapAsync(async x => var mapped = await result.MapAsync(async x =>
{ {
await Task.Delay(1); await Task.Delay(1);
return x.ToString(); return x.ToString(CultureInfo.InvariantCulture);
}); });
Assert.That(mapped.IsSuccess, Is.True); Assert.That(mapped.IsSuccess, Is.True);
Assert.That(mapped.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42")); Assert.That(mapped.Match(succ: v => v, fail: _ => ""), Is.EqualTo("42"));
@ -431,7 +432,7 @@ public class ResultTTests
var mapped = await result.MapAsync(async x => var mapped = await result.MapAsync(async x =>
{ {
await Task.Delay(1); await Task.Delay(1);
return x.ToString(); return x.ToString(CultureInfo.InvariantCulture);
}); });
Assert.That(mapped.IsFaulted, Is.True); Assert.That(mapped.IsFaulted, Is.True);
Assert.That(mapped.Exception, Is.SameAs(exception)); Assert.That(mapped.Exception, Is.SameAs(exception));
@ -804,4 +805,4 @@ public class ResultTTests
var bottom2 = Result<int>.Bottom; var bottom2 = Result<int>.Bottom;
Assert.That(bottom1.Equals(bottom2), Is.True); Assert.That(bottom1.Equals(bottom2), Is.True);
} }
} }

View File

@ -33,7 +33,7 @@ public class TestResourceLoader : IResourceLoader<TestResource>
public async Task<TestResource> LoadAsync(string path) public async Task<TestResource> LoadAsync(string path)
{ {
await Task.Delay(10); // 模拟异步加载 await Task.Delay(10).ConfigureAwait(false); // 模拟异步加载
return Load(path); return Load(path);
} }
@ -99,7 +99,7 @@ public class ResourceManagerTests
[Test] [Test]
public async Task LoadAsync_Should_Load_Resource() public async Task LoadAsync_Should_Load_Resource()
{ {
var resource = await _resourceManager.LoadAsync<TestResource>("test/resource1.txt"); var resource = await _resourceManager.LoadAsync<TestResource>("test/resource1.txt").ConfigureAwait(false);
Assert.That(resource, Is.Not.Null); Assert.That(resource, Is.Not.Null);
Assert.That(resource!.Content, Is.EqualTo("Content 1")); Assert.That(resource!.Content, Is.EqualTo("Content 1"));
@ -404,4 +404,4 @@ public class ResourceManagerTests
handle2!.Dispose(); handle2!.Dispose();
Assert.That(_resourceManager.IsLoaded("test/resource2.txt"), Is.False); Assert.That(_resourceManager.IsLoaded("test/resource2.txt"), Is.False);
} }
} }

View File

@ -525,7 +525,7 @@ public sealed class TestAsyncState : IState, IAsyncState
/// <param name="from">从哪个状态进入</param> /// <param name="from">从哪个状态进入</param>
public async Task OnEnterAsync(IState? from) public async Task OnEnterAsync(IState? from)
{ {
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
EnterCalled = true; EnterCalled = true;
EnterCallCount++; EnterCallCount++;
EnterFrom = from; EnterFrom = from;
@ -537,7 +537,7 @@ public sealed class TestAsyncState : IState, IAsyncState
/// <param name="to">离开到哪个状态</param> /// <param name="to">离开到哪个状态</param>
public async Task OnExitAsync(IState? to) public async Task OnExitAsync(IState? to)
{ {
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
ExitCalled = true; ExitCalled = true;
ExitCallCount++; ExitCallCount++;
ExitTo = to; ExitTo = to;
@ -550,7 +550,7 @@ public sealed class TestAsyncState : IState, IAsyncState
/// <returns>是否允许转换</returns> /// <returns>是否允许转换</returns>
public async Task<bool> CanTransitionToAsync(IState target) public async Task<bool> CanTransitionToAsync(IState target)
{ {
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
CanTransitionToCallCount++; CanTransitionToCallCount++;
return AllowTransition; return AllowTransition;
} }

View File

@ -674,7 +674,7 @@ public sealed class ConcreteAsyncStateV2 : IState, IAsyncState
/// <param name="from">从哪个状态进入</param> /// <param name="from">从哪个状态进入</param>
public async Task OnEnterAsync(IState? from) public async Task OnEnterAsync(IState? from)
{ {
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
EnterCalled = true; EnterCalled = true;
EnterCallCount++; EnterCallCount++;
EnterFrom = from; EnterFrom = from;
@ -686,7 +686,7 @@ public sealed class ConcreteAsyncStateV2 : IState, IAsyncState
/// <param name="to">退出到哪个状态</param> /// <param name="to">退出到哪个状态</param>
public async Task OnExitAsync(IState? to) public async Task OnExitAsync(IState? to)
{ {
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
ExitCalled = true; ExitCalled = true;
ExitCallCount++; ExitCallCount++;
ExitTo = to; ExitTo = to;
@ -699,7 +699,7 @@ public sealed class ConcreteAsyncStateV2 : IState, IAsyncState
/// <returns>如果可以转换则返回true否则返回false</returns> /// <returns>如果可以转换则返回true否则返回false</returns>
public async Task<bool> CanTransitionToAsync(IState target) public async Task<bool> CanTransitionToAsync(IState target)
{ {
await Task.Delay(1); await Task.Delay(1).ConfigureAwait(false);
CanTransitionToAsyncAction?.Invoke(target); CanTransitionToAsyncAction?.Invoke(target);
return AllowTransitions; return AllowTransitions;
} }
@ -731,4 +731,4 @@ public sealed class ConcreteAsyncStateV2 : IState, IAsyncState
{ {
throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state"); throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state");
} }
} }