测试代码
测试代码1
1 using DefaultUnDo; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace TestDemo 9 { 10 class Program 11 { 12 static void Main() 13 { 14 Console.WriteLine("========== DefaultUnDo 完整测试(.NET 4.8 修正版) ==========\n"); 15 16 RunTest("基本值类型操作", TestBasicValue); 17 RunTest("Do 便捷重载(设置值)", TestDoSetter); 18 RunTest("字符串操作", TestString); 19 RunTest("集合操作", TestCollection); 20 RunTest("多个连续操作", TestMultipleOperations); 21 RunTest("边界情况 - 无操作可撤销/重做", TestBoundary); 22 RunTest("Clear 清理历史", TestClear); 23 RunTest("复杂对象操作", TestComplexObject); 24 RunTest("嵌套操作", TestNestedOperation); 25 RunTest("状态查询", TestStateQuery); 26 RunTest("事务操作(Transaction)", TestTransaction); 27 RunTest("事务嵌套与混合", TestTransactionNested); 28 29 Console.WriteLine("\n========== 所有测试通过 =========="); 30 Console.ReadKey(); 31 } 32 33 // ----- 辅助方法 ----- 34 static void RunTest(string name, Action testAction) 35 { 36 Console.WriteLine($"▶ {name}"); 37 try 38 { 39 testAction(); 40 Console.WriteLine($" ✓ 通过\n"); 41 } 42 catch (Exception ex) 43 { 44 Console.WriteLine($" ✗ 失败: {ex.Message}\n"); 45 throw; 46 } 47 } 48 49 static void AssertEqual<T>(T expected, T actual, string message = "") 50 { 51 if (!EqualityComparer<T>.Default.Equals(expected, actual)) 52 { 53 throw new Exception($"断言失败: {message},期望值: {expected},实际值: {actual}"); 54 } 55 } 56 57 static void AssertTrue(bool condition, string message = "") 58 { 59 if (!condition) 60 { 61 throw new Exception($"断言失败: {message}"); 62 } 63 } 64 65 static void AssertFalse(bool condition, string message = "") 66 { 67 if (condition) 68 { 69 throw new Exception($"断言失败: {message}"); 70 } 71 } 72 73 // 断言调用 action 会抛出指定类型的异常,并可验证异常消息包含指定片段 74 static void AssertThrows<TException>(Action action, string expectedMessagePart = null) where TException : Exception 75 { 76 try 77 { 78 action(); 79 throw new Exception($"预期抛出 {typeof(TException).Name},但未抛出任何异常"); 80 } 81 catch (TException ex) 82 { 83 if (!string.IsNullOrEmpty(expectedMessagePart) && !ex.Message.Contains(expectedMessagePart)) 84 { 85 throw new Exception($"异常消息应包含 \"{expectedMessagePart}\",实际为: {ex.Message}"); 86 } 87 // 符合预期 88 } 89 catch (Exception ex) 90 { 91 throw new Exception($"预期抛出 {typeof(TException).Name},但抛出了 {ex.GetType().Name}: {ex.Message}"); 92 } 93 } 94 95 // ========== 测试1: 基本值类型操作 ========== 96 static void TestBasicValue() 97 { 98 IUnDoManager manager = new UnDoManager(); 99 int number = 42; 100 101 manager.Do( 102 () => number = 100, 103 () => number = 42 104 ); 105 AssertEqual(100, number, "执行后 number 应为 100"); 106 107 manager.Undo(); 108 AssertEqual(42, number, "撤销后 number 应为 42"); 109 110 manager.Redo(); 111 AssertEqual(100, number, "重做后 number 应为 100"); 112 } 113 114 // ========== 测试2: Do 便捷重载 ========== 115 static void TestDoSetter() 116 { 117 IUnDoManager manager = new UnDoManager(); 118 int score = 10; 119 120 manager.Do(v => score = v, 99, score); 121 AssertEqual(99, score, "执行后 score 应为 99"); 122 123 manager.Undo(); 124 AssertEqual(10, score, "撤销后 score 应为 10"); 125 126 manager.Redo(); 127 AssertEqual(99, score, "重做后 score 应为 99"); 128 } 129 130 // ========== 测试3: 字符串操作 ========== 131 static void TestString() 132 { 133 IUnDoManager manager = new UnDoManager(); 134 string name = "Alice"; 135 136 manager.Do( 137 () => name = "Bob", 138 () => name = "Alice" 139 ); 140 AssertEqual("Bob", name, "执行后 name 应为 Bob"); 141 142 manager.Undo(); 143 AssertEqual("Alice", name, "撤销后 name 应为 Alice"); 144 145 manager.Redo(); 146 AssertEqual("Bob", name, "重做后 name 应为 Bob"); 147 } 148 149 // ========== 测试4: 集合操作 ========== 150 static void TestCollection() 151 { 152 IUnDoManager manager = new UnDoManager(); 153 var list = new List<string> { "A", "B", "C" }; 154 155 string itemToAdd = "D"; 156 manager.Do( 157 () => list.Add(itemToAdd), 158 () => list.RemoveAt(list.Count - 1) 159 ); 160 AssertEqual(4, list.Count, "添加后列表长度应为 4"); 161 AssertEqual("D", list[3], "最后一个元素应为 D"); 162 163 manager.Undo(); 164 AssertEqual(3, list.Count, "撤销后列表长度应为 3"); 165 AssertEqual("C", list[2], "最后一个元素应为 C"); 166 167 manager.Redo(); 168 AssertEqual(4, list.Count, "重做后列表长度应为 4"); 169 } 170 171 // ========== 测试5: 多个连续操作 ========== 172 static void TestMultipleOperations() 173 { 174 IUnDoManager manager = new UnDoManager(); 175 int a = 1, b = 2; 176 177 manager.Do(() => a = 10, () => a = 1); 178 manager.Do(() => b = 20, () => b = 2); 179 180 AssertEqual(10, a, "a 应为 10"); 181 AssertEqual(20, b, "b 应为 20"); 182 183 manager.Undo(); 184 AssertEqual(10, a, "撤销一次后 a 应为 10"); 185 AssertEqual(2, b, "撤销一次后 b 应为 2"); 186 187 manager.Undo(); 188 AssertEqual(1, a, "撤销两次后 a 应为 1"); 189 AssertEqual(2, b, "撤销两次后 b 应为 2"); 190 191 manager.Redo(); 192 AssertEqual(10, a, "重做一次后 a 应为 10"); 193 AssertEqual(2, b, "重做一次后 b 应为 2"); 194 195 manager.Redo(); 196 AssertEqual(10, a, "重做两次后 a 应为 10"); 197 AssertEqual(20, b, "重做两次后 b 应为 20"); 198 } 199 200 // ========== 测试6: 边界情况 - 无操作可撤销/重做 ========== 201 static void TestBoundary() 202 { 203 IUnDoManager manager = new UnDoManager(); 204 205 AssertFalse(manager.CanUndo, "初始 CanUndo 应为 false"); 206 AssertFalse(manager.CanRedo, "初始 CanRedo 应为 false"); 207 208 // 调用 Undo 应抛出 InvalidOperationException 209 AssertThrows<InvalidOperationException>(() => manager.Undo(), "No operation to undo"); 210 AssertThrows<InvalidOperationException>(() => manager.Redo(), "No operation to redo"); 211 212 // 再检查状态仍为 false 213 AssertFalse(manager.CanUndo, "操作后 CanUndo 仍应为 false"); 214 AssertFalse(manager.CanRedo, "操作后 CanRedo 仍应为 false"); 215 } 216 217 // ========== 测试7: Clear 清理历史 ========== 218 static void TestClear() 219 { 220 IUnDoManager manager = new UnDoManager(); 221 int x = 5; 222 223 manager.Do(() => x = 100, () => x = 5); 224 AssertEqual(100, x, "执行后 x 应为 100"); 225 AssertTrue(manager.CanUndo, "Clear 前 CanUndo 应为 true"); 226 227 manager.Clear(); 228 AssertEqual(100, x, "Clear 后 x 仍为 100"); 229 AssertFalse(manager.CanUndo, "Clear 后 CanUndo 应为 false"); 230 231 // Clear 后调用 Undo 应抛出异常 232 AssertThrows<InvalidOperationException>(() => manager.Undo(), "No operation to undo"); 233 // 确保 x 未变 234 AssertEqual(100, x, "Clear 后 Undo 不应改变 x"); 235 } 236 237 // ========== 测试8: 复杂对象操作 ========== 238 static void TestComplexObject() 239 { 240 IUnDoManager manager = new UnDoManager(); 241 var person = new Person { Name = "John", Age = 30 }; 242 243 string oldName = person.Name; 244 int oldAge = person.Age; 245 246 manager.Do( 247 () => { person.Name = "Jane"; person.Age = 25; }, 248 () => { person.Name = oldName; person.Age = oldAge; } 249 ); 250 AssertEqual("Jane", person.Name, "执行后 Name 应为 Jane"); 251 AssertEqual(25, person.Age, "执行后 Age 应为 25"); 252 253 manager.Undo(); 254 AssertEqual("John", person.Name, "撤销后 Name 应为 John"); 255 AssertEqual(30, person.Age, "撤销后 Age 应为 30"); 256 257 manager.Redo(); 258 AssertEqual("Jane", person.Name, "重做后 Name 应为 Jane"); 259 AssertEqual(25, person.Age, "重做后 Age 应为 25"); 260 } 261 262 // ========== 测试9: 嵌套操作 ========== 263 static void TestNestedOperation() 264 { 265 IUnDoManager manager = new UnDoManager(); 266 int counter = 0; 267 268 manager.Do(() => 269 { 270 counter++; 271 // 在操作内部再执行一个操作 272 manager.Do(() => counter += 10, () => counter -= 10); 273 }, () => counter = 0); 274 275 AssertEqual(11, counter, "执行后 counter 应为 11"); 276 277 // 一次撤销会回退整个嵌套操作,直接回到初始状态 278 manager.Undo(); 279 AssertEqual(0, counter, "撤销一次后 counter 应为 0"); 280 281 // 重做会重放整个嵌套操作 282 manager.Redo(); 283 AssertEqual(11, counter, "重做后 counter 应为 11"); 284 } 285 286 // ========== 测试10: 状态查询 ========== 287 static void TestStateQuery() 288 { 289 IUnDoManager manager = new UnDoManager(); 290 291 AssertFalse(manager.CanUndo, "初始 CanUndo 应为 false"); 292 AssertFalse(manager.CanRedo, "初始 CanRedo 应为 false"); 293 294 int testVal = 0; 295 manager.Do(() => testVal = 1, () => testVal = 0); 296 AssertTrue(manager.CanUndo, "执行后 CanUndo 应为 true"); 297 AssertFalse(manager.CanRedo, "执行后 CanRedo 应为 false"); 298 299 manager.Undo(); 300 AssertFalse(manager.CanUndo, "撤销后 CanUndo 应为 false"); 301 AssertTrue(manager.CanRedo, "撤销后 CanRedo 应为 true"); 302 303 manager.Redo(); 304 AssertTrue(manager.CanUndo, "重做后 CanUndo 应为 true"); 305 AssertFalse(manager.CanRedo, "重做后 CanRedo 应为 false"); 306 } 307 308 // ========== 测试11: 事务操作 ========== 309 static void TestTransaction() 310 { 311 IUnDoManager manager = new UnDoManager(); 312 int value = 0; 313 314 // 使用事务将多个操作合并为一个原子操作 315 using (IUnDoTransaction transaction = manager.BeginTransaction()) 316 { 317 manager.Do(() => value = 10, () => value = 0); 318 manager.Do(() => value = 20, () => value = 10); 319 // 提交事务,将操作合并到历史中 320 transaction.Commit(); 321 } 322 323 AssertEqual(20, value, "事务执行后 value 应为 20"); 324 AssertTrue(manager.CanUndo, "事务提交后应可撤销"); 325 326 // 一次撤销应回退整个事务 327 manager.Undo(); 328 AssertEqual(0, value, "撤销事务后 value 应为 0"); 329 AssertFalse(manager.CanUndo, "撤销后 CanUndo 应为 false"); 330 331 // 重做应重放整个事务 332 manager.Redo(); 333 AssertEqual(20, value, "重做事后 value 应为 20"); 334 } 335 336 // ========== 测试12: 事务嵌套与混合 ========== 337 static void TestTransactionNested() 338 { 339 IUnDoManager manager = new UnDoManager(); 340 int a = 0, b = 0; 341 342 // 外层事务 343 using (IUnDoTransaction outer = manager.BeginTransaction()) 344 { 345 manager.Do(() => a = 5, () => a = 0); 346 347 // 内层事务 348 using (IUnDoTransaction inner = manager.BeginTransaction()) 349 { 350 manager.Do(() => b = 10, () => b = 0); 351 inner.Commit(); // 内层提交 352 } 353 354 outer.Commit(); // 外层提交 355 } 356 357 AssertEqual(5, a, "a 应为 5"); 358 AssertEqual(10, b, "b 应为 10"); 359 AssertTrue(manager.CanUndo, "应可撤销"); 360 361 // 一次撤销回退所有 362 manager.Undo(); 363 AssertEqual(0, a, "撤销后 a 应为 0"); 364 AssertEqual(0, b, "撤销后 b 应为 0"); 365 } 366 } 367 368 // 辅助类 369 public class Person 370 { 371 public string Name { get; set; } 372 public int Age { get; set; } 373 } 374 }
测试代码2
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using DefaultUnDo; namespace TestDemo1 { internal static class Program { private static int _passed, _failed; private static void Main() { Console.WriteLine("================ DefaultUnDo 降级后功能验证 ================"); Console.WriteLine(); Run("1. 基本 Do/Undo/Redo", Test_BasicDoUndoRedo); Run("2. Version 属性变更通知", Test_VersionNotify); Run("3. GroupUnDo (params 数组)", Test_GroupUnDo); Run("4. ValueUnDo<T>", Test_ValueUnDo); Run("5. UnDoField<T>", Test_UnDoField); Run("6. 事务 Commit (多操作合并)", Test_TransactionCommit); Run("7. 事务回滚 (不 Commit 自动撤销)", Test_TransactionRollback); Run("8. 嵌套事务", Test_NestedTransaction); Run("9. 集合扩展 IList.AsUnDo", Test_IListAsUnDo); Run("10. 集合扩展 ICollection.DoClear", Test_DoClear); Run("11. 集合扩展 ISet.AsUnDo (IntersectWith)", Test_ISetAsUnDo); Run("12. 集合扩展 IDictionary.AsUnDo", Test_IDictAsUnDo); Run("13. 合并 TryMerge (ValueUnDo 连续合并)", Test_Merge); Run("14. Clear 清空历史", Test_Clear); Run("15. 参数校验 (null 抛异常)", Test_ArgumentNullChecks); Run("16. struct 值相等性", Test_StructEquality); Console.WriteLine(); Console.WriteLine($"================ 汇总:通过 {_passed},失败 {_failed} ================"); if (_failed > 0) { Console.WriteLine("❌ 存在失败,库有问题!"); Console.ReadKey(); Environment.Exit(1); } else { Console.WriteLine("✅ 全部通过,降级改造未破坏功能。"); Console.ReadKey(); } } private static void Run(string title, Action test) { Console.WriteLine($"[{title}]"); try { test(); } catch (Exception ex) { Check("未抛异常完成", false, $"抛出 {ex.GetType().Name}: {ex.Message}"); } Console.WriteLine(); } private static void Check(string name, bool ok, string detail = "") { if (ok) { _passed++; Console.WriteLine($" [PASS] {name}"); } else { _failed++; Console.WriteLine($" [FAIL] {name} {detail}"); } } // 1. 基本 Do/Undo/Redo private static void Test_BasicDoUndoRedo() { var m = new UnDoManager(); int v = 0; var cmd = new UnDo(() => v = 1, () => v = 0); m.Do(cmd); Check("Do 后 v=1", v == 1, $"v={v}"); m.Undo(); Check("Undo 后 v=0", v == 0, $"v={v}"); m.Redo(); Check("Redo 后 v=1", v == 1, $"v={v}"); Check("CanUndo", m.CanUndo); Check("CanRedo=false (Redo后无可Redo)", !m.CanRedo); } // 2. Version 属性变更通知(覆盖 field 关键字改后备字段) private static void Test_VersionNotify() { var m = new UnDoManager(); int notifies = 0; ((INotifyPropertyChanged)m).PropertyChanged += (s, e) => notifies++; int v = m.Version; m.Do(new UnDo(() => { }, () => { })); Check("Do 后触发 PropertyChanged", notifies > 0, $"notifies={notifies}"); Check("Version 递增", m.Version == v + 1, $"期望{v + 1} 实际{m.Version}"); notifies = 0; m.Undo(); Check("Undo 触发 PropertyChanged", notifies > 0, $"notifies={notifies}"); } // 3. GroupUnDo(覆盖 params IUnDo[] 改动) private static void Test_GroupUnDo() { var m = new UnDoManager(); var log = new List<int>(); var g = new GroupUnDo( new UnDo(() => log.Add(1), () => log.Add(-1)), new UnDo(() => log.Add(2), () => log.Add(-2)), new UnDo(() => log.Add(3), () => log.Add(-3))); m.Do(g); Check("Group Do 顺序 1,2,3", log.SequenceEqual(new[] { 1, 2, 3 }), string.Join(",", log)); log.Clear(); m.Undo(); Check("Group Undo 倒序 -3,-2,-1", log.SequenceEqual(new[] { -3, -2, -1 }), string.Join(",", log)); log.Clear(); m.Redo(); Check("Group Redo 顺序 1,2,3", log.SequenceEqual(new[] { 1, 2, 3 }), string.Join(",", log)); } // 4. ValueUnDo<T> private static void Test_ValueUnDo() { var m = new UnDoManager(); int v = 10; m.Do(new ValueUnDo<int>(x => v = x, 20, 10)); Check("Do 后 v=20", v == 20, $"v={v}"); m.Undo(); Check("Undo 后 v=10", v == 10, $"v={v}"); m.Redo(); Check("Redo 后 v=20", v == 20, $"v={v}"); } // 5. UnDoField<T>(覆盖 UnDoFieldChange struct) private static void Test_UnDoField() { var m = new UnDoManager(); var f = new UnDoField<int>(m, 1); f.Value = 2; Check("set 后 Value=2", f.Value == 2, $"v={f.Value}"); m.Undo(); Check("Undo 后 Value=1", f.Value == 1, $"v={f.Value}"); m.Redo(); Check("Redo 后 Value=2", f.Value == 2, $"v={f.Value}"); int direct = f; Check("隐式转换 T", direct == 2, $"v={direct}"); } // 6. 事务 Commit(覆盖 _commands=new List + GroupUnDo ToArray) private static void Test_TransactionCommit() { var m = new UnDoManager(); var list = new List<string>(); using (var t = m.BeginTransaction()) { m.Do(new UnDo(() => list.Add("A"), () => list.Remove("A"))); m.Do(new UnDo(() => list.Add("B"), () => list.Remove("B"))); m.Do(new UnDo(() => list.Add("C"), () => list.Remove("C"))); t.Commit(); } Check("Commit 后 A,B,C", list.SequenceEqual(new[] { "A", "B", "C" }), string.Join(",", list)); m.Undo(); Check("一次 Undo 撤销整组 (ToArray 改动点)", list.Count == 0, $"count={list.Count}"); m.Redo(); Check("Redo 恢复整组", list.SequenceEqual(new[] { "A", "B", "C" }), string.Join(",", list)); } // 7. 事务回滚(不 Commit,Dispose 倒序撤销) private static void Test_TransactionRollback() { var m = new UnDoManager(); var list = new List<string>(); int vBefore = m.Version; using (var t = m.BeginTransaction()) { m.Do(new UnDo(() => list.Add("X"), () => list.Remove("X"))); m.Do(new UnDo(() => list.Add("Y"), () => list.Remove("Y"))); // 不 Commit } Check("回滚后 list 空", list.Count == 0, $"count={list.Count}"); Check("回滚后 CanUndo=false", !m.CanUndo); Check("回滚后 Version 不变", m.Version == vBefore, $"期望{vBefore} 实际{m.Version}"); } // 8. 嵌套事务 private static void Test_NestedTransaction() { var m = new UnDoManager(); var list = new List<string>(); using (var outer = m.BeginTransaction()) { m.Do(new UnDo(() => list.Add("O"), () => list.Remove("O"))); using (var inner = m.BeginTransaction()) { m.Do(new UnDo(() => list.Add("I"), () => list.Remove("I"))); inner.Commit(); } outer.Commit(); } Check("嵌套事务提交 O,I", list.SequenceEqual(new[] { "O", "I" }), string.Join(",", list)); m.Undo(); Check("一次 Undo 撤销全部", list.Count == 0, $"count={list.Count}"); } // 9. IList.AsUnDo private static void Test_IListAsUnDo() { var m = new UnDoManager(); var list = new List<int> { 1, 2 }.AsUnDo(m); list.Add(3); Check("Add 后 1,2,3", list.SequenceEqual(new[] { 1, 2, 3 }), string.Join(",", list)); m.Undo(); Check("Undo Add 后 1,2", list.SequenceEqual(new[] { 1, 2 }), string.Join(",", list)); list.Move(0, 1); Check("Move 后 2,1", list.SequenceEqual(new[] { 2, 1 }), string.Join(",", list)); m.Undo(); Check("Undo Move 后 1,2", list.SequenceEqual(new[] { 1, 2 }), string.Join(",", list)); } // 10. DoClear(覆盖 source.ToArray 改动) private static void Test_DoClear() { var m = new UnDoManager(); ICollection<int> col = new List<int> { 1, 2, 3 }.AsUnDo(m); m.DoClear(col); Check("DoClear 清空", col.Count == 0); m.Undo(); Check("Undo DoClear 恢复 1,2,3 (ToArray 改动点)", col.SequenceEqual(new[] { 1, 2, 3 }), string.Join(",", col)); } // 11. ISet.AsUnDo + IntersectWith(覆盖 [..other.Where] ToList 改动) private static void Test_ISetAsUnDo() { var m = new UnDoManager(); ISet<int> set = new HashSet<int> { 1, 2, 3, 4 }.AsUnDo(m); set.IntersectWith(new[] { 2, 4, 6 }); Check("IntersectWith 后 2,4", set.SequenceEqual(new[] { 2, 4 }), string.Join(",", set)); m.Undo(); Check("Undo IntersectWith 恢复 1,2,3,4 (ToList 改动点)", set.SequenceEqual(new[] { 1, 2, 3, 4 }), string.Join(",", set)); } // 12. IDictionary.AsUnDo private static void Test_IDictAsUnDo() { var m = new UnDoManager(); var dict = new Dictionary<string, int>().AsUnDo(m); dict.Add("k", 99); Check("Add 后 dict[k]=99", dict["k"] == 99); m.Undo(); Check("Undo Add 后无 k", !dict.ContainsKey("k")); m.Redo(); Check("Redo 后 dict[k]=99", dict["k"] == 99); } // 13. 合并 TryMerge(覆盖 IMergeableUnDo,UnDoStack.Push 调 TryMerge) private static void Test_Merge() { var old = ValueUnDo.MergeInterval; ValueUnDo.MergeInterval = TimeSpan.FromSeconds(5); try { var m = new UnDoManager(); int v = 0; m.Do(new ValueUnDo<int>(x => v = x, 1, 0)); m.Do(new ValueUnDo<int>(x => v = x, 2, 0)); m.Do(new ValueUnDo<int>(x => v = x, 3, 0)); Check("合并后最终 v=3", v == 3, $"v={v}"); m.Undo(); Check("一次 Undo 回到 v=0 (合并为一个操作)", v == 0, $"v={v}"); } finally { ValueUnDo.MergeInterval = old; } } // 14. Clear 清空历史 private static void Test_Clear() { var m = new UnDoManager(); m.Do(new UnDo(() => { }, () => { })); m.Do(new UnDo(() => { }, () => { })); m.Clear(); Check("Clear 后 CanUndo=false", !m.CanUndo); Check("Clear 后 CanRedo=false", !m.CanRedo); } // 15. 参数校验(覆盖 ThrowIfNull 替换) private static void Test_ArgumentNullChecks() { var m = new UnDoManager(); Check("Do(null) 抛 ArgumentNullException", Throws<ArgumentNullException>(() => m.Do(null!))); Check("DoAdd(null manager) 抛 ArgumentNullException", Throws<ArgumentNullException>(() => ((IUnDoManager)null!).DoAdd(new List<int>(), 1))); Check("UnDoField(null manager) 抛 ArgumentNullException", Throws<ArgumentNullException>(() => new UnDoField<int>(null!))); Check("GroupUnDo(null 命令元素) 抛 ArgumentException", Throws<ArgumentException>(() => new GroupUnDo((IUnDo)null!))); } // 16. struct 值相等性(覆盖手写 Equals) private static void Test_StructEquality() { var c1 = new UnDoFieldChange<int>(1, 2); var c2 = new UnDoFieldChange<int>(1, 2); var c3 = new UnDoFieldChange<int>(1, 3); Check("UnDoFieldChange 相等", c1.Equals(c2)); Check("UnDoFieldChange 不等", !c1.Equals(c3)); Check("UnDoFieldChange GetHashCode 一致", c1.GetHashCode() == c2.GetHashCode()); var list = new List<int>(); var o1 = new UnDoCollectionOperation(list, UnDoCollectionAction.ICollectionAdd, 1); var o2 = new UnDoCollectionOperation(list, UnDoCollectionAction.ICollectionAdd, 2); Check("UnDoCollectionOperation.Collection", o1.Collection == list); Check("UnDoCollectionOperation.Action", o1.Action == UnDoCollectionAction.ICollectionAdd); Check("UnDoCollectionOperation.Parameters 长度", o1.Parameters.Length == 1); Check("UnDoCollectionOperation 自等", o1.Equals(o1)); Check("UnDoCollectionOperation 不同参数不等", !o1.Equals(o2)); } private static bool Throws<T>(Action a) where T : Exception { try { a(); return false; } catch (T) { return true; } catch { return false; } } } }

浙公网安备 33010602011771号