泛型,委託,閉包

32、總是優先考慮泛型

例如實現自己的List類

 

33、避免在泛型類型中聲明靜態成員

如果不想要不同類型共享相同是屬性,就別定義靜態成員

 

34、爲泛型參數設定約束

爲泛型添加約束後,可以使用約束相應的功能  例如new()  或者 :Person(某個自定義的類)

 

35、使用default爲泛型變量指定初始值

if()
{
    return xx;
}else
{
    return xx;
}
return default(T);

36、使用FCL中的委託聲明

使用Action Fun Predicate代替自定義的委託

 

37、使用Lambda表達式代替方法和匿名方法

Lambda本質就是匿名方法,但是寫起來更方便,看着整潔

 

38、小心閉包中的陷阱

List<Action> lists = new List<Action>();
for (int i = 0; i < 5; i++)
{
    //int j = i;
    Action a1 = () => Console.WriteLine(i);
    lists.Add(a1);
}
foreach (Action item in lists)
{
    item();
}

當我們使用匿名函數或Lambda並且要利用for循環裏面的索引值,同時此方法是在for循環之後調用的,那麼就會出現閉包問題

因爲() = > v "返回變量 v 的當前值",而不是創建該委託時"v“ 的返回值 。閉包”變量“,而不是閉包”值“。所以在”for“循環中的添加的匿名函數,只是返回了變量i 而不是i的值。所以知道f() 被真正執行時,i已經是values.Count 值啦,所以會拋出”超出索引範圍“。

C#是如何實現閉包的呢?

class Program
{
    static void Main(string[] args)
    {
        List<Action> lists = new List<Action>();
        TempClass tempClass = new TempClass();
        for (tempClass.i = 0; tempClass.i < 5; tempClass.i++)
        {
            Action a1 = tempClass.TempFuc;
            lists.Add(a1);
        }
        foreach (Action item in lists)
        {
            item();
        }
    }
}

class TempClass
{
    public int i;
    public void TempFuc()
    {
        Console.WriteLine(i.ToString());
    }
}

編譯器會自動給我們創建一個類,在循環中每次會爲這個類的一個實例變量i賦值

按照下面這樣寫就會避免閉包

for (int i = 0; i < 5; i++)
{
    int temp = i;
    Action a1 = () => Console.WriteLine(temp);
    lists.Add(a1);
}

上面的代碼和下面代碼其實是等效的

for (int i = 0; i < 5; i++)
{
    TempClass tempClass = new TempClass();
    tempClass.i = i;
    Action a1 = tempClass.TempFuc;
    lists.Add(a1);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章