作者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)
→ help0430:第一二點可以參考某些設計模式,第三點可以參考Action<T> 04/07 12:28
→ F23ko:已經寫出來了啊! 就是我這一篇的code。我是在擔心效率問題.. 04/07 23:08
→ F23ko:匿名函式的話.... 只要包函那個函式的{}中的資源都不會被釋 04/07 23:09
→ F23ko:放的樣子....似乎很占記憶體 04/07 23:10