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

    近来在小组C#快速成长团队 讨论了若干话题,有些感觉不错,特总结与大家分享。
    当然,所谓话题,重点在于进行讨论,是否是最佳实践也属于大家的个人之见。以下观点若有差错,尽情蹂躏。
    1:String str1 = “str1”+ 9; 和String str2 = “str2”+ 9.ToString(); 哪个效率高
    可以知道“str1”+ 9,在运行时会完成一次装箱行为。9.ToString(),没有发生装箱行为,Int类型的ToString()方法的实际原型为:
    public override String ToString() {
    return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
    }
    可能有人会问,那是不是原型中的Number.FormatInt32方法会发生装箱行为呢?实际Number.FormatInt32方法是一个非托管的方法,原型如下:
    [MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
    public static extern string FormatInt32(int value, string format, NumberFormatInfo info);
    它通过直接操作内存来进行int到string的转换,效率要比装箱高很多。
    所以,答案是:后者
    装箱为什么会带来性能损耗,因为它内部发生了太多事情:
    1:首先,为值类型在托管堆中分配内存。内存总量除了值类型本身所分配的内存外,还要加上类型对象指针和同步块索引;
    2:值类型的值复制到新分配的堆内存;
    3:返回已经成为引用类型的对象的地址;

    2:as,is转型比强制转型的优势

    优势在于as,is 不抛出异常,如果转型失败,则返回null

    强制转型则会抛出异常,导致代码必须处理异常,效率低。

    值得注意的是,as只能转型基本类型,对于基本类别如int等的转型,只能使用强制转型或is。


    3:readonly和const的区别或者说哪个更好

    1:const天然就是static的,所以不能用static修饰;readonly无此限制;
    2:const只能修饰基元类型;readonly无此限制;
    3:const是编译期常量;readonly为运行期常量,其初始值除了在初始化器还可以在类型的构造函数中设定;
    4:const经编译后,以实际值代替了变量(可查看IL验证),效率显然要高一些,可用到关键算法中,除此之外,与readonly比没有任何优势。

    4:初始化器和构造器的异同
    初始化器实际是语法糖,经编译后,它在构造函数的最开始执行。也就是说,初始化器可以理解为构造函数的一部分。

    5:枚举在使用中的注意事项

    1:如果不指定枚举的零值,会带来什么问题;

    static Week week;

    static void Main(string[] args)
    {
    Console.WriteLine(week);
    }

    即使未给week赋值,也会打印出零值。

    2:如果为枚举中的元素指定了相同的值,又会带来什么问题。

    会导致相等型比较的时候出现与预期不符的结果
    3:建议不给枚举显式指定值,但是如果枚举用于位运算则要为其元素指定2的指数幂值。

    6:为什么LINQ语句都要开始于from而不是select
    显而易见的原因是为了智能感知,要让他在输入LINQ查询的时候起作用,from子句就必须在最前面;如:
    var AllCustomers = from Customer in db.Customers 
    select new { Customer.ContactName, Customer.Country }; 

    7:dynamic可以用它来简化反射。
    使用反射,调用方代码:
    DynamicSample dynamicSample = new DynamicSample();
    var addMethod
    = typeof(DynamicSample).GetMethod("Add");
    int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2 });

    在使用dynamic后,我们的代码看上去更简洁了,并且在可控的范围内减少了一次拆箱的机会:
    dynamic dynamicSample2 = new DynamicSample();
    int re2 = dynamicSample2.Add(1, 2);

    8:foreach不能替代for的原因
    1: 首先,对集合的每次增删操作(是不是全部集合?不得而知,但是起码是绝大部分集合),都会让集合的version字段+1,foreach采用的是迭代器模式,每次迭代的时候都要判断version是不是保持一致,如果不一致,则抛出异常。而for没有这方面的限制。所以,采用

    List<int> list = new List<int>() { 0, 1, 2, 3 };
    foreach (int item in list)
    {
    list.Remove(item);
    Console.WriteLine(item.ToString());
    }

    会抛出异常,而改为for则不会。这是for不能被foreach取代叼的最重要原因。

    2:foreach默认调用集合的迭代器的Dispose方法,如果该迭代器继承了IDispose方法的话。

    9:区别IComparable<T>和IComparer<T>
    前者IComparable<T>为类提供默认的比较器,而IComparer<T>可以为集合类提供更多的比较器。具体查看http://www.cnblogs.com/luminji/archive/2010/09/30/1839038.html
     
    10:LINQ和比较器及迭代器优缺点比较
    要进行排序和比较,传统的方式,存在两个问题:
    1:可扩展性太低,如果存在新的排序要求,就得实现新的比较器;
    2:对代码的侵入性太高,为类型继承了接口,增加了新的方法;
    可参见博文的讨论:http://www.cnblogs.com/luminji/archive/2011/02/17/1956723.html

    在我们自己的代码中强烈建议你利用LINQ带来便捷性,但我们仍需掌握比较器、迭代器、索引器的原理,以便我们更好地理解LINQ的思想,写出更加高质量的代码。


    更多内容,尽情期待下一集。。。
  • 相关阅读:
    被学长教会的高斯消元法Gauss
    KMP字符串匹配算法翔解❤
    fkwの题目(祝松松生日快乐!)
    NOI-linux下VIM的个人常用配置
    从2017年暑假到现在手打的模板↑_↑
    【テンプレート】初级数据结构
    【テンプレート】高精
    DP(第二版)
    luogu P1029 最大公约数和最小公倍数问题
    贪心题整理
  • 原文地址:https://www.cnblogs.com/luminji/p/1967934.html
Copyright © 2011-2022 走看看