zoukankan      html  css  js  c++  java
  • C#高效编程话题集2(每期10话题)

    第一期话题在:C#高效编程话题集1(每期10话题)

    C#快速成长团队第二期话题来到。欢迎进入C#快速成长团队进行讨论。

    1:确保集合的线程安全

    如果使用.net4.0,有新的线程安全集合类
    新的 System.Collections.Concurrent 命名空间引入了多个新的线程安全集合类,可在需要时随时提供对项的无锁访问,并在锁适用时提供细粒度锁定。 在多线程方案中使用这些类应获得优于集合类型(例如, ArrayList 和 List <(Of <(T >)>))的性能。

    除了System.Collections.Concurrent空间下集合外,非泛型集合使用
    lock(非泛型集合对象.SyncRoot)进行锁定达到集合线程安全目的
    泛型集合使用
    static object sycObj = new object(); //是否static看具体应用
    lock (sycObj)
    {
         //操作集合。
    }

    2:循环中先求长度还是使用list.Count,哪个效率高

    第一类:

    int len = list.Count; 

    for(int i; i<len; i++)

    {

         迭代

    }

    第二类:

    for(int i; i<list.Count; i++)

    {

         迭代

    }

    答案是一样高。

    第一种方法完全没有必要,很多人可能以为那样会为代码带来效率,而实际上是不会给效率带来任何提升。
    因为事实上,索引器内部,为了安全期间,还是会去求整个list的count的。将两者代码贴出来可能会更好的理解这一点:
    public T this[int index]
    {
        get
        {
           if (index >= this._size)
          {
              ThrowHelper.ThrowArgumentOutOfRangeException();
          }
          return this._items[index];
        }
        set
        {
            if (index >= this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException();
            }
            this._items[index] = value;
            this._version++;
        }
    }


    public int Count
    {
        get
        {
            return this._size;
        }
    }

    3:善用延迟求值

    以List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};为例,说明linq查询中的延迟求值和主动求值。

    List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    var temp1 = from c in list where c > 5 select c;
    var temp2 = (from c in list where c > 5 select c).ToList<int>();
    list[0] = 11;
    Console.Write("temp1: ");
    foreach (var item in temp1)
    {
        Console.Write(item.ToString() + " ");
    }
    Console.Write("\ntemp2: ");
    foreach (var item in temp2)
    {
        Console.Write(item.ToString() + " ");
    }

    4:谨慎泛型类型中的静态成员

    static void Main(string[] args)
    {
         MyList<int> list1 = new MyList<int>();
         MyList<int> list2 = new MyList<int>();
         MyList<string> list3 = new MyList<string>();
         Console.WriteLine(MyList<int>.Count);
         Console.WriteLine(MyList<string>.Count);
    }
    class MyList<T>
    {
         public static int Count { get; set; }
         public MyList()
         {
             Count++;
         }

    }

    代码输出是莫子?

    只要知道 MyList<int> 和 MyList<string> 是两个不同的类型,这题就不难理解了。.NET 中类型参数不同的封闭泛型类型是不同的类型。

    5:小心闭包中的陷阱

    for (int i = 0; i < 10; i++)
    {
         Action t = () =>
        {
            Console.WriteLine("t1:" + i.ToString());
        };
        t.BeginInvoke(null, null);
    }

    以上代码的输出为?

    当闭包中引用了外部的局部变量或者方法参数的时候,C#会把该变量编译成一个类的实例字段,顶楼的代码编译后实际上等效于:
    TempClass tp = new TempClass();
    for (tp.i = 0; tp.i < 10; tp.i++)
    {
      Action t = tp.TempMethod;
      t.BeginInvoke(null, null);
    }
    TempClass是C#编译器自动生成的类,其定义大概是这样:
    class TempClass
    {
      public int i;
      public void TempMethod()
      {
        Console.Writeline("t1:" + i.ToString());
      }
    }
    因为只循环10次,几乎一瞬间就完了,因此第一个异步委托还没开始执行 tp.i 就等于10了

    6:event关键字的作用

    既然使用委托也能实现回调,为什么又需要event关键字。答曰:event 最大的作用就是防止在类的外部触发类的事件。

    7:区分IEnumerable<T>和IQueryable<T>

    本地数据源用IEnumerable<T>,远程数据源用IQueryable<T>。
    针对LinqLINQ TO to OBJECTS,使用Enumerable中的扩展方法对本地集合进行排序、查询等操作,查询参数接受的是Func< >。Func< >叫做谓语表达式,相当于一个委托。针对LinqLINQ TO to SQL则使用Querable中的扩展方法,它接受的参数是Expression< >。Expression< >用于包装Func< >。LinqLINQ TO to SQL引擎最终会将表达式树转化成为相应的SQL语句,然后在数据库中执行。

      

    8:选择正确的集合

    查看此文吧:http://www.cnblogs.com/luminji/archive/2011/03/24/1993393.html

    9:泛型参数的约束是不是应该叫约定更好

    在泛型的使用过程中,常常使用到的一个功能就是为泛型参数设定约束。约束听上去像是限制了泛型参数的使用范围,而实际上,约束本身确实拓展了泛型参数的使用。

    一个没有约束的泛型参数,只能具有object的行为和属性,而一个指定约束为Student的泛型参数,却可以使用类型Student的所有公开属性和方法。

    所以,俺觉得约束这个词翻译的实在不好,叫约定多好。

    10:减少使用自定义委托

    FCL中的3个(或者说3系列)委托已经满足了大部分自定义委托的需求,所以基本上不再需要自定义委托了。

    它们是:

    Action表示接受0个或多个输入参数,执行一段代码,但是没有任何返回值;

    Func表示接受0个或多个输入参数,执行一段代码,同时有返回值;

    Predicate表示定义一组条件并判断参数是否符合条件;

     更多话题,期待下一期。

    C#高效编程话题集3(每期10话题)

  • 相关阅读:
    Quartz.Net定时器
    Lucene.Net 实现搜索功能
    哈希表 STL map
    买卖股票的最佳时机I II III IV
    [离散化]人潮最多的時段( Interval Partitioning Problem )
    动态规划[入门]3-更难的矩阵取数问题
    动态规划[入门3]-多重背包问题
    动态规划[入门]2-循环数组最大子段和
    catalan卡塔兰数
    逆波兰表达式
  • 原文地址:https://www.cnblogs.com/luminji/p/1994097.html
Copyright © 2011-2022 走看看