作者F23ko (纯洁)
看板C_Sharp
标题[心得] Dictionary<T,T> + delegate
时间Wed Mar 31 20:07:10 2010
Dictionary<Tkey,Titem> + delegate
MSDN中有提到用Dictionary装delegate的方法
自己拿来变化了一下
http://msdn.microsoft.com/zh-tw/library/z4ka55h8(v=VS.90).aspx
accessor-declarations 的用法之一是公开大量的事件但不配置每个事件的栏位
,而是改用字典来储存事件执行个体。
不过,这只在您拥有大量的事件,但预期大多数事件都不会实作的情况下才有用。
不过.... 我想请问红字部分为什麽会这样说?
自己在想stg的演算法时
想了一些东西:
1.物件移动时,至少有位置、速度、加速度等三个变数要处理
所受到的因素不只一种,而且形式也不一定
重力场:需连结到另一个位置,计算距离後求得受力
由於位置会变,所以要用ref连结到目标
这必须每次计算
空气阻力:固定往後方,要取的物件的姿势去计算
用极座标较方便
且也是必须每次都计算
特殊移动方式:
假设我设计一个叫做「後燃器」的功能
能在五秒内向前方提供+3的加速度
这在处理起来很麻烦
我必须宣告一个栏位记录这个方法用的时间参数
而且也没办法同时要使用多个後燃器
也是每个影格都要计算
下略...........
2.另外关於持续性特效之类的
如果用下面这种写法也是很麻烦的事,很不乾净,看了觉得讨厌:
if (is中毒) this.中毒效果();
if (is晕眩) this.晕眩效果();
下略................
3.委派本身就有限制型别,如果该方法必须给予参数
而我的委派不是同个参数类型,那就必须用匿名函式
虽然上面那种问题可以写个委派或是事件解决
但这会造成移除时的困难
而且,委派或匿名方法,没办法预先丢变数下去
即使用匿名方式放变数下去,之後变数被更动时,执行内容也会跟着变
例如:
for (int i=0;i<5;i++)
{
委派1 += () => {Console.Write(i)}
}
执行 委派1 时,出来的会是55555,而不是01234
=======================================================================
所以,基於:
1.能事先塞不同变数下去,让委派执行
且在原函式中的变数受到更动时,不会跟着变
2.能轻易移除,或是自主移除
3.写程式上很简洁,且共用范围广
所以我想了用Dictionary<T,T>去装匿名方法的办法
如果是在STG中的话,我只要在建立新变因时
(例如在场上新增一个重力场)
就对所有场上物件底下的「控制位置的class」
下达 以「重力场的参照(ref)」计算吸引力的命令
那麽,只要我在Update()中执行所有字典下的委派,就能达到这个效果了
=======================================================================
http://nopaste.csie.org/38d94
public delegate void 委派();
public class Test
{
private int id = 0;
private int ID
{
get { return id++; } //避免ID重覆
}
private Dictionary<int, 委派> 待执行的程式字典 = new Dictionary<int, 委派>();
public int 我是控制方法的方法(int 次数,string 代号)
{
int i = 0;
int 这次方法的执行ID = ID;
待执行的程式字典.Add(
这次方法的执行ID,
() =>
{
if (i++ < 次数) 我是要执行的程式(代号, i);
else
{
待执行的程式字典.Remove(这次方法的执行ID);
Console.WriteLine("移除了:{0}", 代号);
}
}
);
return 这次方法的执行ID;
}
private void 我是要执行的程式(string 代号,int 次数)
{
Console.WriteLine("执行了:{0} 第{1}次", 代号, 次数);
}
public bool 执行所有字典中的程式()
{
if (待执行的程式字典.Count == 0) return true;
//如果有方法被移除,会造成位在後方的索引往前移,所以要从後面开始执行
for (int i = 待执行的程式字典.Count-1; i > -1; i--)
{
//注意,不可用「待执行的程式字典[i]」去取得方法,因为[]中是Tkey
待执行的程式字典.ElementAt(i).Value();
}
return false;
}
}
class Program
{
static void Main(string[] args)
{
Test A = new Test();
A.我是控制方法的方法(3, "方法一");
A.我是控制方法的方法(2, "方法二");
A.我是控制方法的方法(4, "方法三");
int i = 1;
bool is结束;
while (true)
{
Console.WriteLine("第 {0} 次执行A的字典集。",i);
is结束 = A.执行所有字典中的程式();
Console.WriteLine("===============================");
Console.WriteLine();
if (is结束) break;
i++;
}
Console.WriteLine("执行完毕");
}
}
--
◢
乡民啊!乡民! 请告诉我谁是最纯洁的人!
◢█ │
PTT │
██
:就是你!Snow White F23ko!│
█◤ ╯
◤ ﹨(╯▽╰ )∕
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 163.27.109.99
※ 编辑: F23ko 来自: 163.27.109.99 (03/31 20:09)
※ 编辑: F23ko 来自: 163.27.109.99 (03/31 20:10)
1F:→ help0430:第一二点可以参考某些设计模式,第三点可以参考Action<T> 04/07 12:28
2F:→ F23ko:已经写出来了啊! 就是我这一篇的code。我是在担心效率问题.. 04/07 23:08
3F:→ F23ko:匿名函式的话.... 只要包函那个函式的{}中的资源都不会被释 04/07 23:09
4F:→ F23ko:放的样子....似乎很占记忆体 04/07 23:10