【读书笔记】编写高质量代码改善C# 建议32-38(⭐泛型和委托)

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);
}

猜你喜欢

转载自blog.csdn.net/qq_33413868/article/details/81460893