FishPlayer

一个喜欢摸鱼的废物

0%

传入Predicate的小事

现在依旧是在项目里负责一些UI业务的编写。前段时间需要需要给游戏中的 popup提示 做一些简单的重构,正好发现了我一直以来都误解的一个小点,决定记下来。

业务的要求就是做那种会弹出来一会儿再消失的提示,比如道具获取之类的UI。

我的做法就是用一个list去存着当前的提示,并 tick 检查它们是否结束,然后移除已经结束的相关数据。
大概的用法如下。

但其实啊,这个做法在 tick 是非常不好的。同事很快地通过 JetBrainsRider 查看 IL Code ,并告诉我,直接这样传入会每次都 new obj 。有比较大的消耗。
所以在这种需要经常 tick 并且条件比较固定的情况下。我们可以创建好 predicate 然后直接重复使用(可以存在成员变量里,这里演示就直接存在本地变量里了)。

最后附上测试代码和结果 测试 count 为 100000

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

public class PredicateTempTest
{
public struct TempPack
{
public int tempValue;
private static Random s_random = new Random(DateTime.Now.Millisecond);
public static TempPack CreateTempPack()
{
TempPack pack = default;
if (s_random == null)
{
s_random = new Random(DateTime.Now.Millisecond);
}
pack.tempValue = s_random.Next(0, 10);
return pack;
}
}

private static List<List<TempPack>> s_tempListContainer = new List<List<TempPack>>(10000);

public static void DoTest(int tempCount)
{
FillTestData(tempCount);
DoTestLambda();
DoTestPassMethod();
DoTestPassExistPredicate();
}

private static void FillTestData(int tempCount)
{
s_tempListContainer.Clear();
s_tempListContainer.Capacity = tempCount;
for (int i = 0; i < tempCount; i++)
{
List<TempPack> tempList = new List<TempPack>(tempCount);
s_tempListContainer.Add(tempList);
for (int j = 0; j < tempCount; j++)
{
tempList.Add(TempPack.CreateTempPack());
}
}
}

private static void DoTestLambda()
{
Console.WriteLine("");
Console.WriteLine("TestLambda start");
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0, containerSize = s_tempListContainer.Count; i < containerSize; i++)
{
List<TempPack> tempList = s_tempListContainer[i];
tempList.Find((existPack) => existPack.tempValue % 5 == 0);
}
stopWatch.Stop();
Console.WriteLine($"TestLambda end, result_{stopWatch.ElapsedMilliseconds}ms");
}

private static void DoTestPassMethod()
{
Console.WriteLine("");
Console.WriteLine("PassMethod start");
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0, containerSize = s_tempListContainer.Count; i < containerSize; i++)
{
List<TempPack> tempList = s_tempListContainer[i];
tempList.Find(CheckPack);
}
stopWatch.Stop();
Console.WriteLine($"PassMethod end, result_{stopWatch.ElapsedMilliseconds}ms");
}

private static void DoTestPassExistPredicate()
{
Console.WriteLine("");
Console.WriteLine("PassExistPredicate start");
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Predicate<TempPack> predicate = new Predicate<TempPack>(CheckPack);
for (int i = 0, containerSize = s_tempListContainer.Count; i < containerSize; i++)
{
List<TempPack> tempList = s_tempListContainer[i];
tempList.Find(predicate);
}
stopWatch.Stop();
Console.WriteLine($"PassExistPredicate end, result_{stopWatch.ElapsedMilliseconds}ms");
}

private static bool CheckPack(TempPack pack)
{
return pack.tempValue % 5 == 0;
}

}