diff --git a/GFramework.Core.Abstractions/Concurrency/LockInfo.cs b/GFramework.Core.Abstractions/Concurrency/LockInfo.cs
new file mode 100644
index 0000000..2f8cc1f
--- /dev/null
+++ b/GFramework.Core.Abstractions/Concurrency/LockInfo.cs
@@ -0,0 +1,46 @@
+// Copyright (c) 2025 GeWuYou
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Runtime.InteropServices;
+
+namespace GFramework.Core.Abstractions.Concurrency;
+
+///
+/// 锁信息(用于调试)
+///
+[StructLayout(LayoutKind.Auto)]
+public readonly struct LockInfo
+{
+ ///
+ /// 锁的键。
+ ///
+ public string Key { get; init; }
+
+ ///
+ /// 当前引用计数。
+ ///
+ public int ReferenceCount { get; init; }
+
+ ///
+ /// 最后访问时间戳(Environment.TickCount64)。
+ ///
+ public long LastAccessTicks { get; init; }
+
+ ///
+ /// 等待队列长度(近似值)。
+ /// 注意:这是一个基于 SemaphoreSlim.CurrentCount 的近似指示器,
+ /// 当 CurrentCount == 0 时表示锁被持有且可能有等待者,返回 1;
+ /// 否则返回 0。这不是精确的等待者数量,仅用于调试参考。
+ ///
+ public int WaitingCount { get; init; }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Abstractions/Concurrency/LockStatistics.cs b/GFramework.Core.Abstractions/Concurrency/LockStatistics.cs
index c875496..f86bb68 100644
--- a/GFramework.Core.Abstractions/Concurrency/LockStatistics.cs
+++ b/GFramework.Core.Abstractions/Concurrency/LockStatistics.cs
@@ -11,11 +11,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+using System.Runtime.InteropServices;
+
namespace GFramework.Core.Abstractions.Concurrency;
///
/// 锁统计信息
///
+[StructLayout(LayoutKind.Auto)]
public readonly struct LockStatistics
{
///
@@ -37,33 +40,4 @@ public readonly struct LockStatistics
/// 累计清理的锁数量
///
public int TotalCleaned { get; init; }
-}
-
-///
-/// 锁信息(用于调试)
-///
-public readonly struct LockInfo
-{
- ///
- /// 锁的键
- ///
- public string Key { get; init; }
-
- ///
- /// 当前引用计数
- ///
- public int ReferenceCount { get; init; }
-
- ///
- /// 最后访问时间戳(Environment.TickCount64)
- ///
- public long LastAccessTicks { get; init; }
-
- ///
- /// 等待队列长度(近似值)
- /// 注意:这是一个基于 SemaphoreSlim.CurrentCount 的近似指示器,
- /// 当 CurrentCount == 0 时表示锁被持有且可能有等待者,返回 1;
- /// 否则返回 0。这不是精确的等待者数量,仅用于调试参考。
- ///
- public int WaitingCount { get; init; }
}
\ No newline at end of file
diff --git a/GFramework.Core.Abstractions/Pause/IPauseStackManager.cs b/GFramework.Core.Abstractions/Pause/IPauseStackManager.cs
index 7c40ab7..11e24b9 100644
--- a/GFramework.Core.Abstractions/Pause/IPauseStackManager.cs
+++ b/GFramework.Core.Abstractions/Pause/IPauseStackManager.cs
@@ -75,7 +75,9 @@ public interface IPauseStackManager : IContextUtility
void UnregisterHandler(IPauseHandler handler);
///
- /// 暂停状态变化事件
+ /// 暂停状态变化事件。
+ /// 事件遵循标准 .NET 事件模式,事件源为触发通知的暂停管理器实例,
+ /// 事件数据由 提供。
///
- event Action? OnPauseStateChanged;
+ event EventHandler? OnPauseStateChanged;
}
\ No newline at end of file
diff --git a/GFramework.Core.Abstractions/Pause/PauseStateChangedEventArgs.cs b/GFramework.Core.Abstractions/Pause/PauseStateChangedEventArgs.cs
new file mode 100644
index 0000000..72a84dd
--- /dev/null
+++ b/GFramework.Core.Abstractions/Pause/PauseStateChangedEventArgs.cs
@@ -0,0 +1,30 @@
+namespace GFramework.Core.Abstractions.Pause;
+
+///
+/// 表示暂停状态变化事件的数据。
+/// 该类型用于向事件订阅者传递暂停组以及该组变化后的暂停状态。
+///
+public sealed class PauseStateChangedEventArgs : EventArgs
+{
+ ///
+ /// 初始化 的新实例。
+ ///
+ /// 发生状态变化的暂停组。
+ /// 暂停组变化后的新状态。
+ public PauseStateChangedEventArgs(PauseGroup group, bool isPaused)
+ {
+ Group = group;
+ IsPaused = isPaused;
+ }
+
+ ///
+ /// 获取发生状态变化的暂停组。
+ ///
+ public PauseGroup Group { get; }
+
+ ///
+ /// 获取暂停组变化后的新状态。
+ /// 为 表示进入暂停,为 表示恢复运行。
+ ///
+ public bool IsPaused { get; }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/Pause/PauseStackManagerTests.cs b/GFramework.Core.Tests/Pause/PauseStackManagerTests.cs
index f682c1b..4705357 100644
--- a/GFramework.Core.Tests/Pause/PauseStackManagerTests.cs
+++ b/GFramework.Core.Tests/Pause/PauseStackManagerTests.cs
@@ -1,6 +1,5 @@
using GFramework.Core.Abstractions.Pause;
using GFramework.Core.Pause;
-using NUnit.Framework;
namespace GFramework.Core.Tests.Pause;
@@ -220,11 +219,11 @@ public class PauseStackManagerTests
PauseGroup? eventGroup = null;
bool? eventIsPaused = null;
- _manager.OnPauseStateChanged += (group, isPaused) =>
+ _manager.OnPauseStateChanged += (_, e) =>
{
eventTriggered = true;
- eventGroup = group;
- eventIsPaused = isPaused;
+ eventGroup = e.Group;
+ eventIsPaused = e.IsPaused;
};
_manager.Push("Test", PauseGroup.Gameplay);
@@ -243,10 +242,10 @@ public class PauseStackManagerTests
var token = _manager.Push("Test");
bool eventTriggered = false;
- _manager.OnPauseStateChanged += (group, isPaused) =>
+ _manager.OnPauseStateChanged += (_, e) =>
{
eventTriggered = true;
- Assert.That(isPaused, Is.False);
+ Assert.That(e.IsPaused, Is.False);
};
_manager.Pop(token);
diff --git a/GFramework.Core/Coroutine/CoroutineSlot.cs b/GFramework.Core/Coroutine/CoroutineSlot.cs
index 38ade65..7821e48 100644
--- a/GFramework.Core/Coroutine/CoroutineSlot.cs
+++ b/GFramework.Core/Coroutine/CoroutineSlot.cs
@@ -17,11 +17,6 @@ internal sealed class CoroutineSlot
///
public CoroutineHandle Handle;
- ///
- /// 协程是否已经开始执行
- ///
- public bool HasStarted;
-
///
/// 协程的优先级
///
diff --git a/GFramework.Core/Events/PriorityEvent.cs b/GFramework.Core/Events/PriorityEvent.cs
index 8704267..8555e93 100644
--- a/GFramework.Core/Events/PriorityEvent.cs
+++ b/GFramework.Core/Events/PriorityEvent.cs
@@ -208,13 +208,10 @@ public class PriorityEvent : IEvent
MergeAndSortHandlers(T t)
{
var (normalSnapshot, contextSnapshot) = CreateSnapshots();
- // 使用快照避免迭代期间修改
+ // 使用统一的投影方法显式固定元组的可空标注,避免 LINQ 在 Concat 时推断出不兼容的签名。
return normalSnapshot
- .Select(h => (h.Priority, Handler: (Action?)(() => h.Handler.Invoke(t)),
- ContextHandler: (Action>?)null, IsContext: false))
- .Concat(contextSnapshot
- .Select(h => (h.Priority, Handler: (Action?)null,
- ContextHandler: (Action>?)h.Handler, IsContext: true)))
+ .Select(h => CreateNormalHandlerInvocation(h, t))
+ .Concat(contextSnapshot.Select(CreateContextHandlerInvocation))
.OrderByDescending(h => h.Priority)
.ToList();
}
@@ -289,6 +286,29 @@ public class PriorityEvent : IEvent
}
}
+ ///
+ /// 将普通事件处理器转换为统一的调用描述。
+ ///
+ /// 要包装的普通处理器。
+ /// 当前触发的事件数据。
+ /// 可与上下文处理器合并排序的统一调用描述。
+ private static (int Priority, Action? Handler, Action>? ContextHandler, bool IsContext)
+ CreateNormalHandlerInvocation(EventHandler handler, T t)
+ {
+ return (handler.Priority, () => handler.Handler.Invoke(t), null, false);
+ }
+
+ ///
+ /// 将上下文事件处理器转换为统一的调用描述。
+ ///
+ /// 要包装的上下文处理器。
+ /// 可与普通处理器合并排序的统一调用描述。
+ private static (int Priority, Action? Handler, Action>? ContextHandler, bool IsContext)
+ CreateContextHandlerInvocation(ContextEventHandler handler)
+ {
+ return (handler.Priority, null, handler.Handler, true);
+ }
+
///
/// 事件处理器包装类,包含处理器和优先级
///
diff --git a/GFramework.Core/Pause/PauseStackManager.cs b/GFramework.Core/Pause/PauseStackManager.cs
index e11e171..dd15fe3 100644
--- a/GFramework.Core/Pause/PauseStackManager.cs
+++ b/GFramework.Core/Pause/PauseStackManager.cs
@@ -80,7 +80,7 @@ public class PauseStackManager : AbstractContextUtility, IPauseStackManager, IAs
// 触发事件
try
{
- OnPauseStateChanged?.Invoke(group, false);
+ RaisePauseStateChanged(group, false);
}
catch (Exception ex)
{
@@ -97,7 +97,7 @@ public class PauseStackManager : AbstractContextUtility, IPauseStackManager, IAs
///
/// 暂停状态变化事件,当暂停状态发生改变时触发。
///
- public event Action? OnPauseStateChanged;
+ public event EventHandler? OnPauseStateChanged;
///
/// 推入一个新的暂停请求到指定的暂停组中。
@@ -488,7 +488,18 @@ public class PauseStackManager : AbstractContextUtility, IPauseStackManager, IAs
}
// 触发事件
- OnPauseStateChanged?.Invoke(group, isPaused);
+ RaisePauseStateChanged(group, isPaused);
+ }
+
+ ///
+ /// 以标准事件模式发布暂停状态变化事件。
+ /// 所有状态变更路径都通过该方法创建统一的事件参数,避免不同调用点出现不一致的载荷。
+ ///
+ /// 发生状态变化的暂停组。
+ /// 暂停组变化后的新状态。
+ private void RaisePauseStateChanged(PauseGroup group, bool isPaused)
+ {
+ OnPauseStateChanged?.Invoke(this, new PauseStateChangedEventArgs(group, isPaused));
}
///
diff --git a/GFramework.Game.Abstractions/Scene/ISceneBehavior.cs b/GFramework.Game.Abstractions/Scene/ISceneBehavior.cs
index 2bb07ee..f56f5d8 100644
--- a/GFramework.Game.Abstractions/Scene/ISceneBehavior.cs
+++ b/GFramework.Game.Abstractions/Scene/ISceneBehavior.cs
@@ -23,9 +23,9 @@ public interface ISceneBehavior : IRoute
{
///
/// 获取场景的唯一标识符。
- /// 用于区分不同的场景实例。
+ /// 该成员显式细化了 在场景路由中的语义,用于区分不同的场景实例。
///
- string Key { get; }
+ new string Key { get; }
///
/// 获取场景的原始对象。
diff --git a/GFramework.Game.Abstractions/Scene/ISceneRouteGuard.cs b/GFramework.Game.Abstractions/Scene/ISceneRouteGuard.cs
index eb3e70e..8680c14 100644
--- a/GFramework.Game.Abstractions/Scene/ISceneRouteGuard.cs
+++ b/GFramework.Game.Abstractions/Scene/ISceneRouteGuard.cs
@@ -31,8 +31,9 @@ public interface ISceneRouteGuard : IRouteGuard
///
/// 异步检查是否允许离开指定场景。
+ /// 该成员显式细化了通用路由守卫的离开检查,使场景守卫在 API 文档中保持场景语义。
///
/// 当前场景的唯一标识符。
/// 如果允许离开则返回 true,否则返回 false。
- ValueTask CanLeaveAsync(string sceneKey);
+ new ValueTask CanLeaveAsync(string sceneKey);
}
\ No newline at end of file
diff --git a/GFramework.Game.Abstractions/UI/IUiPageBehavior.cs b/GFramework.Game.Abstractions/UI/IUiPageBehavior.cs
index 8e84067..51e693a 100644
--- a/GFramework.Game.Abstractions/UI/IUiPageBehavior.cs
+++ b/GFramework.Game.Abstractions/UI/IUiPageBehavior.cs
@@ -48,10 +48,10 @@ public interface IUiPageBehavior : IRoute
///
- /// 获取键值
+ /// 获取页面的唯一键值,并显式细化 在 UI 路由中的语义。
///
/// 返回当前对象的键标识符
- string Key { get; }
+ new string Key { get; }
///
diff --git a/GFramework.Game.Abstractions/UI/IUiRouteGuard.cs b/GFramework.Game.Abstractions/UI/IUiRouteGuard.cs
index fff03c9..d1a7ee4 100644
--- a/GFramework.Game.Abstractions/UI/IUiRouteGuard.cs
+++ b/GFramework.Game.Abstractions/UI/IUiRouteGuard.cs
@@ -17,9 +17,10 @@ public interface IUiRouteGuard : IRouteGuard
ValueTask CanEnterAsync(string uiKey, IUiPageEnterParam? param);
///
- /// 离开UI前的检查
+ /// 离开UI前的检查。
+ /// 该成员显式细化了通用路由守卫的离开检查,使 UI 守卫在 API 文档中保持 UI 语义。
///
/// 当前UI标识符
/// true表示允许离开,false表示拦截
- ValueTask CanLeaveAsync(string uiKey);
+ new ValueTask CanLeaveAsync(string uiKey);
}
\ No newline at end of file
diff --git a/docs/zh-CN/core/pause.md b/docs/zh-CN/core/pause.md
index 7f81f95..b4b9ca2 100644
--- a/docs/zh-CN/core/pause.md
+++ b/docs/zh-CN/core/pause.md
@@ -100,8 +100,8 @@ void ClearAll();
void RegisterHandler(IPauseHandler handler);
void UnregisterHandler(IPauseHandler handler);
-// 状态变化事件
-event Action? OnPauseStateChanged;
+// 状态变化事件
+event EventHandler? OnPauseStateChanged;
```
## 基本用法
@@ -377,16 +377,16 @@ public partial class PauseIndicator : IController
_pauseManager.OnPauseStateChanged += OnPauseStateChanged;
}
- private void OnPauseStateChanged(PauseGroup group, bool isPaused)
- {
- Console.WriteLine($"暂停状态变化: 组={group}, 暂停={isPaused}");
-
- if (group == PauseGroup.Global)
- {
- if (isPaused)
- {
- ShowPauseIndicator();
- }
+ private void OnPauseStateChanged(object? sender, PauseStateChangedEventArgs e)
+ {
+ Console.WriteLine($"暂停状态变化: 组={e.Group}, 暂停={e.IsPaused}");
+
+ if (e.Group == PauseGroup.Global)
+ {
+ if (e.IsPaused)
+ {
+ ShowPauseIndicator();
+ }
else
{
HidePauseIndicator();
@@ -705,7 +705,7 @@ public partial class ProperCleanup : IController
_pauseManager.OnPauseStateChanged -= OnPauseChanged;
}
- private void OnPauseChanged(PauseGroup group, bool isPaused) { }
+ private void OnPauseChanged(object? sender, PauseStateChangedEventArgs e) { }
}
```
@@ -743,13 +743,13 @@ public partial class PauseMenu : Control
// 方案 2: 监听暂停事件
var pauseManager = this.GetUtility();
- pauseManager.OnPauseStateChanged += (group, isPaused) =>
- {
- if (group == PauseGroup.Global)
- {
- Visible = isPaused;
- }
- };
+ pauseManager.OnPauseStateChanged += (_, e) =>
+ {
+ if (e.Group == PauseGroup.Global)
+ {
+ Visible = e.IsPaused;
+ }
+ };
}
}
```
@@ -887,15 +887,15 @@ public class PauseEventBridge : AbstractSystem
{
var pauseManager = this.GetUtility();
- pauseManager.OnPauseStateChanged += (group, isPaused) =>
- {
- // 发送暂停事件
- this.SendEvent(new GamePausedEvent
- {
- Group = group,
- IsPaused = isPaused
- });
- };
+ pauseManager.OnPauseStateChanged += (_, e) =>
+ {
+ // 发送暂停事件
+ this.SendEvent(new GamePausedEvent
+ {
+ Group = e.Group,
+ IsPaused = e.IsPaused
+ });
+ };
}
}
diff --git a/docs/zh-CN/godot/pause.md b/docs/zh-CN/godot/pause.md
index a511316..7f40ae4 100644
--- a/docs/zh-CN/godot/pause.md
+++ b/docs/zh-CN/godot/pause.md
@@ -44,7 +44,7 @@ public interface IPauseStackManager : IContextUtility
int GetPauseDepth(PauseGroup group = PauseGroup.Global);
// 暂停状态变化事件
- event Action? OnPauseStateChanged;
+ event EventHandler? OnPauseStateChanged;
}
```
@@ -477,12 +477,12 @@ public partial class PauseIndicator : Label
pauseManager.OnPauseStateChanged -= OnPauseStateChanged;
}
- private void OnPauseStateChanged(PauseGroup group, bool isPaused)
+ private void OnPauseStateChanged(object? sender, PauseStateChangedEventArgs e)
{
- if (group == PauseGroup.Global)
+ if (e.Group == PauseGroup.Global)
{
- Text = isPaused ? "游戏已暂停" : "游戏运行中";
- Visible = isPaused;
+ Text = e.IsPaused ? "游戏已暂停" : "游戏运行中";
+ Visible = e.IsPaused;
}
}
}
@@ -502,16 +502,16 @@ public partial class PauseDebugger : Node
pauseManager.OnPauseStateChanged += OnPauseStateChanged;
}
- private void OnPauseStateChanged(PauseGroup group, bool isPaused)
+ private void OnPauseStateChanged(object? sender, PauseStateChangedEventArgs e)
{
var pauseManager = this.GetUtility();
GD.Print($"=== 暂停状态变化 ===");
- GD.Print($"组: {group}");
- GD.Print($"状态: {(isPaused ? "暂停" : "恢复")}");
- GD.Print($"深度: {pauseManager.GetPauseDepth(group)}");
+ GD.Print($"组: {e.Group}");
+ GD.Print($"状态: {(e.IsPaused ? "暂停" : "恢复")}");
+ GD.Print($"深度: {pauseManager.GetPauseDepth(e.Group)}");
- var reasons = pauseManager.GetPauseReasons(group);
+ var reasons = pauseManager.GetPauseReasons(e.Group);
if (reasons.Count > 0)
{
GD.Print($"原因:");
@@ -609,9 +609,9 @@ public partial class PauseDebugger : Node
7. **使用事件监听暂停状态**:实现响应式 UI
```csharp
- pauseManager.OnPauseStateChanged += (group, isPaused) =>
+ pauseManager.OnPauseStateChanged += (_, e) =>
{
- UpdateUI(isPaused);
+ UpdateUI(e.IsPaused);
};
```