• c#的default、using和yield使用小结


    一、default的应用场合

    1、switch...case
    在switch语句中,如果没有任何case表达式与开关值匹配,则控制传递给跟在可选default标签后的语句。如果没有default标签,则控制传递到switch以外。
    对于c#,为了便于维护,建议default项最好要写。
    示例代码:

    Code

    2、在泛型类和泛型方法中,在预先未知以下情况时,如何将默认值分配给参数化类型T:
    (1)T是引用类型还是值类型;
    (2)如果T为值类型,则它是数值还是结构。
    示例代码:

        public class GenericClass<T>
        {
            
    public static T GetDefaultT<T>(T obj)
            {
                obj 
    = default(T); //将默认值分配给参数化类型T
                return obj;
            }
        }

    备注:  给定参数化类型T的一个变量obj,只有当T为数值类型而且不是结构时,语句t = 0才能正常使用;只有当T为引用类型时,语句obj= null才有效。
    使用default关键字,对于数值类型会返回零,对于引用类型会返回空,对于结构,此关键字将返回初始化为零或空的每个结构成员,具体取决于这些结构是值类型还是引用类型。
    看下面的代码:

    Code

    二、using的应用场合
    1、直接引入命名空间
    using System.Data.SqlClient; //引入命名空间
    2.using别名。using + 别名 = 包括详细命名空间信息的具体的类型。
    这种做法有个好处就是当同一个cs引用了两个不同的命名空间,但两个命名空间都包括了一个相同名字的类型的时候。当需要用到这个类型的时候,就每个地方都要用详细命名空间的办法来区分这些相同名字的类型。而用别名的方法会更简洁,用到哪个类就给哪个类做别名声明就可以了。
    注意:并不是说两个名字重复,给其中一个用了别名,另外一个就不需要用别名了,如果两个都要使用,则两个都需要用using来定义别名的。
    例如我们用以下语句引入using System.Data.SqlClient命名空间:
    using SqlServer=using System.Data.SqlClient;
    这时我们就可以用 SqlServer表示using System.Data.SqlClient命名空间,给程序书写带来方便。
    3、using语句定义一个范围,在该范围内处理对象。
    当年刚学asp.net那会,曾经对照着书本,吭哧吭哧动手写了很多类似下面的代码:

    Code

    直到遇到SqlHelper,才省了很多力气花在业务逻辑上,当年真是...,呵呵。
    言归正传,什么时候适合用using呢?当在某个代码段中使用了类的实例,而希望无论因为什么原因,只要离开了这个代码段就自动调用这个类实例的Dispose方法。要达到这样的目的,用try...finally是可以的,但用using看起来更方便和简洁。看下面的代码:

    Code

     我们看到,using确实比try...finally少几行代码,不过,它们的性能怎么样呢?看两个方法各自生成的对应的IL:
    (1)使用using

    (2)使用try...finally

    原来它们的性能几乎是一样的。上面的两段IL可以作为using和try...finally性能的参照。如果你在程序中经常try...catch或者using,对性能的影响是很明显的。
    需要引起注意的是,using实例化一个对象的时候,对应的类必须实现IDisposable接口,比如我们延续上面的代码,增加一个如下方法:

            static void Test()
            {
                
    using (Program program = new Program()) //编译器报错,Program类必须要实现IDisposable接口
                {
                    
    //do something
                }
            }

    正像注释写的那样,类Program必须实现IDisposable接口,写成class Program : IDisposable{...}这样就可以了。
    三、yield的应用
    1、迭代器块中用于向枚举数对象提供值或发出迭代结束信号。
    它的形式如下:
    yield return <expression>;或者yield break;
    下面看一个示例: 

    Code

    2、几个要注意的地方 
    (1)、计算表达式并以枚举数对象值的形式返回;expression 必须可以隐式转换为迭代器的 yield 类型。
    (2)、yield 语句只能出现在iterator 块中,该块可用作方法、运算符或访问器的体。
    这类方法、运算符或访问器的体受以下约束的控制:
    a、不允许不安全块。
    b、方法、运算符或访问器的参数不能是 ref 或 out。
    c、yield 语句不能出现在匿名方法中。
    (3)、当和expression一起使用时,yield return语句不能出现在catch块中或含有一个或多个catch子句的 try 块中。

    3、最后,为了深入理解迭代,我们有必要介绍一下.net两个和迭代关联密切的接口:IEnumerable和IEnumerator
    (1)、IEnumerable和IEnumerator元数据对比
    a、IEnumerator

    Code

    b、IEnumerable

    Code

    (2)、说明
    IEnumerator:提供在普通集合中遍历的接口,有Current,MoveNext(),Reset(),其中Current属性返回的是object类型,另外两个是实例方法;
    IEnumerable: 暴露一个IEnumerator,支持在普通集合中的遍历;
    IEnumerator<T>:继承自IEnumerator,有Current属性,返回的是T类型;
    IEnumerable<T>:继承自IEnumerable,暴露一个IEnumerator<T>,支持在泛型集合中遍历。

    (3)总结
    a、通过分析(1)中的源码,你也可以从这两个接口的用词选择上,看出其不同:IEnumerable是一个声明式的接口,声明实现该接口的类是“可枚举(enumerable)”的,但并没有说明如何实现iterator;IEnumerator是一个实现式的接口,IEnumerator类就是一个iterator。
    b、一个集合要支持foreach方式的遍历,必须实现IEnumerable接口(即必须以某种方式返回IEnumerator对象);
    c、IEnumerator对象具体实现了iterator(通过内部的MoveNext(),Reset(),Current)。
    d、IEnumerable和IEnumerator通过IEnumerable的GetEnumerator()方法建立了连接,客户端可以通过IEnumerable的GetEnumerator()得到IEnumerator对象,所以从实质上来讲,将GetEnumerator()看作IEnumerator对象的工厂方法也未尝不可。


     


     


    作者:Jeff Wong
    出处:http://jeffwongishandsome.cnblogs.com/
    本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。

  • 相关阅读:
    Makefile 之 $(Q)
    LeetCode-50-Pow(x, n)
    LeetCode-49. Group Anagrams
    全排列问题全面解析
    LeetCode-47. Permutations II
    LeetCode-46. Permutations
    LeetCode-43. Multiply Strings
    LeetCode-40. Combination Sum II
    LeetCode-39. Combination Sum
    LeetCode-36. Valid Sudoku
  • 原文地址:https://www.cnblogs.com/jeffwongishandsome/p/1504377.html
Copyright © 2020-2023  润新知