• C#2.0语法上的变化


    C#2.0语法上的变化:

    ①泛型:

      为什么要引入泛型?
      举个例子比较好理解:例如定义一个System.Collection.ArrayList,里面的元素是object类型的,当从中取出的时候需要作强制类型转换ClassA tmp 
    = myArrayList[0as ClassA;这有两方面问题,一是强制类型转换的性能开销,二是类型安全(编译通过但是运行有可能出错)。在.net1.0中类似的情况是比较多的,引入泛型是为了较好地解决此问题。

    所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。
    还是看看代码吧:
    class Stack<T>
    {
      
    private T[] store;
      
    private int size;
      
    public Stack()//构造函数
      {
        store 
    = new T[10]; size=0;
      }

      
    public void Push(T tmp)
      
    {
        store[size
    ++= tmp;
      }

      
    public T Pop
      
    {
        
    return store[--size];
      }
     
    }

    上面就是一个泛型的实现,在实例化的时候该类的时候我们可以这样声名
    Stack
    <int> aaa = new Stack<int>();
    那么就约束了只能往这个堆栈里放int类型,例如aaa.Push(
    17);是可以的;
    但是aaa.Push(
    "123");编译就会不通过。

    class C<U,V> {}    
    class D: C<string,int> {}    
    class E<U,V>: C<U, V> {}    
    class F<U,V>: C<stringint> {}    

    上面这些都是一些泛型的实现,这里就不一一解释了
    ~
    泛型还可以应用于接口和委托,实际编程时还有一些实际问题。
    值得一提的是下面这个例子:(where)
    class MyClass<S,T>
        where S: A     
    // S继承自A
        where T: B     // T继承自B
    {}

    ②匿名方法与迭代器;


    匿名方法其实没什么,对比一下下面这两段代码就明白了:
    (C# 
    1.0):
    Button1.click 
    += new EventHandler(Button1_Click);
    private void Button1_Click(object sender,EventArgs e)
    {
           TextBox1.Text 
    = "123";
    }

    有了匿名方法之后(C# 
    2.0):
    Button1.Click 
    += delegate {
                      TextBox1.Text 
    = "123";
    }

    关于匿名方法,老实说,偶认为只是为了可以省掉几行代码,比较方便地处理委托,属于C#编译器的“小花招”而已


    然后是“迭代器”:
    在没有这个东东的时候如果需要创建一个集合(可用于foreach循环),需要如此实现
    Public 
    class MyCollection : Ienumerable {
    public MYEnumerator GetEnumerator(){
        
    return new MyEnumerator(this);
    }

    public class MyEnumerator : Ienumerator{
    public void Reset(){ … }
    public bool MoveNext(){ … }
    public int Current{ … }
    object IEnumerator.Currentget{ … } }
         }

    }

    有了“迭代器”之后,这样就可以:
    public class Stack<T>: IEnumerable<T>
    {
           T[] items;
           
    int count;
           
    public void Push(T data) {…}
           
    public T Pop(){…}
           
    public Ienumerator<T> GetEnumerator(){
                  
    for (int I = count – 1; i >=0;--i){
                                  yield 
    return items[i];
                }

    }

    比较简单,看看就能明白,有两个地方稍有点新鲜的:
    1)增加了yield关键字;
    2)使用迭代器创建倒序遍历:
    Public Ienumerable
    <T> Bottom ToTop{
            
    get {
                         
    for(int I = 0;i < count; i++>){
                                       yield 
    return items[i];
                   }

        }
    }


    ③分部类型定义:

    分部类型允许我们将一个类、结构或者接口分成几个部分,分别实现在几个不用的.cs文件中。当然,各个部分的命名空间是要相同的,访问保护修饰符也不能互相冲突。

    为了实现这个东西,引入了半个关键字partial,之所以叫半个,是因为只有和class、
    struct、interface放在一起时,才有关键字的含义。

    分部类型的实用意义偶倒是想到一个,就是我们有一些代码文件是通过某些工具生成的(例如用一些映射工具或者自己写的代码生成工作,去生成一些基本的实体类、数据访问类等),这些代码文件我们又不希望跟手工增加的代码放在一起,就可以分开n个部分来放。

    最后来段简单代码作为例子:
    partial 
    class MyClass
    {
      
    public void test1()
      
    {.}
    }


    partial 
    class MyClass
    {
      
    public void test2()
      
    {.}
    }

    代码可以这样写,最终编译器还是会把各个部分编译到一起的,没有实质区别。

    ④Nullable 泛型结构:

    Nullable 泛型结构允许一个值类型具有“空值”意义,从而方便很多场合的运算,如数据库中的空字段。
    int? a= null;
    if(a == null)
    {
      
    // a如果为空,则.;
    }

    else
    {
      
    // a如果不为空,则.;
    }



    空属类型实际上是一个泛型类型System.Nullable
    <T> 。
      

    ⑤静态类:

    问题真是一个比一个简单,静态类就是一个只包含静态成员的类。
    例子
    static class MyStaticClass
    {
         
    public const int aaa;
         
    public static void Test1()
         
    {
           
    //……
         }

    }

     

    数据访问
    ①模型的调整:

    例如在ado.net1.0里,SqlConnection、OleDbConnection等,并没有一个共同的基类,而是通过继承接口 IDbConnection实现的,现在,则有了一个基类DbConnection,这可方便了一些,我们可针对基类编写数据库访问的代码,而不用关注具体的数据库类型,有利于数据访问层与数据库的分离
    ~

    ②关于DataSet(DataTable)的优化:

    首先是新的索引引擎,看看例子:
    DataTable dt 
    = new DataTable();
    dt.Columns.Add(
    "field1");
    dt.Columns.Add(
    "field2");
    dt.PrimaryKey 
    = new DataColumn[] { dt.Columns[0] };//这句是关键,否则验证不了
    for (int i = 0; i < 200000; i++)
         dt.Rows.Add(
    new object[] { i, DateTime.Now });

    上面这段代码在.net1.1执行需要40
    ~50秒; 在.net2.0中运行在10秒左右

    其次是真正的二进制序列化;

    将上面这个包含有20万条记录的DataTable序列化成文件:

    dt.RemotingFormat 
    = SerializationFormat.Binary;//这个在.net1.1是没有的
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
    System.IO.FileStream fs 
    = new System.IO.FileStream(@"D:\test1.txt", System.IO.FileMode.CreateNew);
    bf.Serialize(fs, dt);
    fs.Close();

    .net1.1得到的是一个大小约29M的文件;.net2.0得到的是约7M的文件;用记事本打开看看就知道差别在哪里。
    在使用Remoting传送DataSet或者DataTable对象的时候,这是一件好事。


    最后,在ado.net2.0中,DataTable更独立了,不像过去那样特别依赖DataSet,有时候不得不把DataTable放到DataSet中仅仅是为了获得某项功能,例如ReadXML()、 WriteXMlSchema()等。

    ③针对MS SQL Server,特别是MS SQL Server2005所作的一些优化:
    这有几方面话题,一是异步处理
    System.Data.SqlClient.SqlCommand cm 
    = new SqlCommand("async=true;..");
    System.IAsyncResult ar 
    = cm.BeginExecuteReader();
    //..
    //do other processing
    System.Data.SqlClient.SqlDataReader dr = cm.EndExecuteReader(ar);


    二是大批量数据操作的优化
    System.Data.SqlClient.SqlBulkCopy bcp 
    = new SqlBulkCopy("连接字符串");
    bcp.WriteToServer(myDataTable);

    三是在ADO.NET 
    2.0针对Sql Server 2005可以同时在Command对象上打开多个DataReader
  • 相关阅读:
    Linux 系统挂载数据盘
    Apache Rewrite规则笔记
    linux fdisk分区笔记
    阿里云linux配置
    linux 下安装mysql相关笔记
    ShopNC目录结构分析
    今天开始出发做ShopNC
    svn相关笔记
    linux学习笔记-不定时更新
    Oracle EBS Java Applet报错:找不到类
  • 原文地址:https://www.cnblogs.com/kokoliu/p/656260.html
Copyright © 2020-2023  润新知