C# DotNet 2.0及3.0 新特性

原文摘自百度百科http://baike.baidu.com/view/406857.htm

以下内容,部分已被修改为自己容易理解的文字,若有不明之处,请参考本文出处。

C# DotNet 2.0新特性

1、 泛型  2、 匿名方法 3、迭代器  4、局部类型 5、空属类型  6、静态类

C# DotNet 3.0新特性

第一个特性:隐式类型化本地变量
第二个特性:匿名类型
第三个特性:隐式类型化数组
第四个特性:对象构造者
第五个特性:集合构造者
第六个特性:Lambda表达式
第七个特性:扩展方法
第八个特性:Linq查询表达式

1、泛型(generics)

    使用泛型,可以定义使用类型参数定义的类和/或方法。当客户端代码实例化类型时,会指定一个特定的类型作为参数。

    /*
    * 泛型可以使一般的集合仍是强类型化——出错的几率更小(因为出错在运行期间发生,提高性能,在使用集合时将可以使用Intellisense特性
    * 要在代码中使用泛型,需要引用System.Collections.Generic命名空间,该命名空间还允许访问Stack、Dictionary、SortedDictionary、List和Queue类的泛型版本。
    * 下面演示Stack类的泛型版本:
    * 在下面的例子中,Stack类显示转换为string类型。这里括号指定集合类型。这个例子使用Stack<string>把Stack类转换为string类型。如果要把它转换为不是string类型的Stack类,例如int,就可以指定Stack<int>。
    * 在创建Stack类时,Stack类中的项集合就转换为指定的类型,所以Stack类不再把项集合转换为object类型,以后(在foreach循环中)再转换为string类型。这个过程称为装箱,该过程是很昂贵的。因为这段代码事先指定了类型,所以使用集合的性能提高了。
    * 泛型除了用于处理集合类型之外,还可以用于处理类、委托、方法等。
    */

    static void Main(string[] args)
    {
      Stack<string> myStack = new Stack<string>();
      myStack.Push("a");
      myStack.Push("b");
      myStack.Push("c");
      Array myArray = myStack.ToArray();
      foreach (string item in myArray)
      {
        Console.WriteLine(item);
      }
    }

top

2、匿名方法

  匿名方法是作为参数传递给委托的代码块。

  /*
  * 匿名方法可以把编程步骤放在一个委托中,以后再执行该委托,而不是创建全新的方法。
  * 例如不使用匿名方法,就要以下面的方式使用委托:
  */

  protected void Page_Load(object sender, EventArgs e)
  {
    this.Button1.Click += ButtonWork;
  }
  void ButtonWork(object sender, EventArgs e)
  {
    Label1.Text = "You clicked the button!";
  }

  /*
  * 但若使用匿名方法,就可以把这些操作直接放在委托中,如下面的例子所示:
  */

  protected void Page_Load(object sender, EventArgs e)
  {
    this.Button1.Click += delegate(object myDelSender, EventArgs myDelEventArgs)
    {
      Label1.Text = "You clicked the button!";
    };
  }

  在使用匿名方法时,不需要创建另外一个方法,而是把需要的代码直接放在委托声明后面。委托执行的语句和步骤放在花括号中,用一个分号结束。

top

3、迭代器(iterator)

  迭代器是这样一种方法,它允许包含集合或数组的类的使用者使用 foreach,in循环访问该集合或数组。

  /*
     * 迭代器允许在自己的定制类型中使用foreach循环。为此,需要使类实现IEnumberable接口,如下所示:
     */
      public class myList
      {
          public IEnumerator GetEnumerator()
          {
              yield return "a";
              yield return "b";
              yield return "c";
          }
      }
      //要使用IEnumerable接口,需要引用System.Collections命名空间。有了该命名空间,就可以迭代定制类了,如下所示:
      protected void Page_Load(object sender, EventArgs e)
      {
          myList IteratorList = new myList();
          foreach (string item in IteratorList)
          {
              Response.Write(item.ToString() + "<br/>");
          }
    }

top

4、局部类型

  局部类型允许我们将一个类的代码分别写在不同的cs文件中。最典型的应用就是使用VS2005创建Form文件时,VS会自动将系统生成的代码与用户代码分开。局部类型通过partial关键字来声明。

  /*
     * 部分类是.NET Framework 2.0的一个新功能,C#也充分利用这一功能。部分类可以把单个类分解到多个类文件中,以后在编译时再把这些文件合并起来。
     * 要创建部分类,只需给要与另一个类合并起来的类使用partial关键字。在要与最初的类合并的类中,partial关键字放在class关键字的前面。例如:有一个简单的类Calculator,如下所示:
     */
  public partial class Calculator
  {
    public int Add(int a, int b)
    {
      return a + b;
    }
  }
    //接着创建第二个类,它要与第一个类关联起来,如下面的例子所示:
  public partial class Calculator
  {
    public int Subtract(int a, int b)
    {
      return a - b;
    }
  }
  class Program
  {
    static void Main(string[] args)
    {
      Calculator theCalculator = new Calculator();
      Console.WriteLine(theCalculator.Subtract(2, 1));
      Console.WriteLine(theCalculator.Add(1, 2));
    }
  }

top

5、空属类型

  空属类型是一种像int,一样可以为空的变量类型。本质上是一种泛型的应用,是System .Nullable<>的一种类型实例化。 由于泛型引入到底层的.NET Framework2.0中,所以现在可以使用System.Nullable<T>创建可空的值类型。这非常适合于创建int类型的可空项集合。

    static void Main(string[] args)
    {
              /*
      * 要创建int类型的可空类型,可以使用下面的语法:
      */
              Nullable<int> x = new Nullable<int>();
              //有一个新的类型修饰符,可用于创建可空类型,如下面的例子所示:
              int? salary=800000;
              salary = null;
              Console.WriteLine(x);
              Console.WriteLine(salary);
        }

top

6、静态类

  静态类是只用于包含静态成员的类型,它既不能实例化,亦不能被继承。

top

第一个特性:隐式类型化本地变量

 这个特性非常简单,有些JavaScript的影子,我们可以统一使用使用"var"关键字来声明局部变量,而不再需要指明变量的确切类型了,变量的确切类型可通过声明变量时的初始值推断出来。这样一来,可以大大简化我们声明局部变量的工作量了。

var a=5;相当于 int a=5;

top

第二个特性:匿名类型

有些时候我们需要临时保存一些运算的中间结果,特别是当这些中间结果是由多个部份组成时,我们常常会去声明一个新的类型,以方便保存这些中间结果。表面上看起来这很正常,而细想之后就会发现,这个新类型只服务于这个函数,其它地方都不会再使用它了,就为这一个函数而去定义一个新的类型,确实有些麻烦。现在,C#3.0中的匿名类型特性就可以很好的解决上面提到的问题,通过匿名类型,我们可以简单使用new { 属性名1=值1, 属性名2=值2, ..... , 属性名n=值n }的形式直接在函数中创建新的类型。

定义:var a=new {name="b",age=15};

使用:a.name的值为字符串"b" ,a.age的值为整型15

top

第三个特性:隐式类型化数组

这个特性是对隐式类型化本地变量的扩展,有了这个特性,将使我们创建数组的工作变得简单。我们可以直接使用"new[]"关键字来声明数组,后面跟上数组的初始值列表。在这里,我们并没有直接指定数组的类型,数组的类型是由初始化列表推断出来的。

定义:var a=new[]{new{name="b"}};

使用:a[0].name的值为字符串"b"

 

top

第四个特性:对象构造者

C#3.0中加入的对象构造者特性,使得对象的初始化工作变得格外简单,我们可以采用类似于数组初始化的方式来初始化类的对象,方法就是直接在创建类对象的表达式后面跟上类成员的初始化代码。

定义:

class Point   

{

   public int X { get; set; }   

  public int Y { get; set; }

  public override string ToString()//重写ToString方法

   {

    return "(" + X.ToString() + ", " + Y.ToString() + ")";

   }

}

我们在定义Point类的X和Y属性时,只须写上该属性的get和set访问器声明,C#编译器会自动为我们生成默认的get和set操作代码,当我们需要定义简单属性时,这个特性非常有用。

初始化:

Point thePoint = new Point() { X = 1, Y = 2 };

使用:

Console.WriteLine("Point(X, Y) = "+ thePoint.ToString());

 

top


上篇文章中介绍了C# 3.0中比较简单的四个特性,分别是隐式类型化本地变量、匿名类型、隐式类型化数组,以及对象构造者,下面我将对C# 3.0中的较复杂,同时也是非常强大的几个特性进行介绍,供大家快速浏览。

第五个特性:集合构造者

C# 3.0中加入的集合构造者特性,可使我们享受到与普通数组一样的待遇,从而在创建集合对象的同时为其指定初始值。为了做到这一点,我们需要让我们的集合实现ICollection<T>接口,在这个接口中,完成初始化操作的关键在于Add函数,当我使用初始化语法为集合指定初始值时,C#编译器将自动调用ICollection<T>中的Add函数将初始列表中的所有元素加入到集合中,以完成集合的初始化操作。

定义:

class StringCollection : ICollection<string>
    {
        public void Add(string item)
        {
            Console.Write(item+"\n");
        }

        #region ICollection<string> 成员


        public void Clear()
        {
           
        }

        public bool Contains(string item)
        {
            return true;
        }

        public void CopyTo(string[] array, int arrayIndex)
        {
           
        }

        public int Count
        {
            get;
            set;
        }
        public bool IsReadOnly
        {
            get;
            set;
        }

        public bool Remove(string item)
        {
            return false;
        }

        #endregion

        #region IEnumerable<string> 成员

        public IEnumerator<string> GetEnumerator()
        {
            List<string> theList = new List<string> { "a" };
            return theList.GetEnumerator();
        }

        #endregion

        #region IEnumerable 成员

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

}

使用:

StringCollection strings = new StringCollection() { "van's", "Brog", "Vicky" };

在这个示例中,编译器会自动为strings对象调用Add方法,以将初始值列表中的所有元素加入到集合中,这里我们只是简单将初始值列表中的元素输出到控制台。

top

第六个特性:Lambda表达式

C# 2.0中加入的匿名代理,简化了我们编写事件处理函数的工作,使我们不再需要单独声明一个函数来与事件绑定,只需要使用delegate关键字在线编写事件处理代码。

而C# 3.0则更进一步,通过Lambda表达式,我们可以一种更为简洁方式编写事件处理代码,新的Lambda事件处理代码看上去就像一个计算表达式,它使用"=>"符号来连接事件参数和事件处理代码。我可以这样写:SomeEvent += 事件参数 => 事件处理代码;

第一种方法:(使用匿名代理)

public static event EventHandler myEvent;

static void Main(string[] args)
{

    myEvent += delegate(object s, EventArgs e){Console.Write(s);};

    myEvent("a\n", null);   

}

第二种方法:(使用Lambda表达式)

public static event EventHandler myEvent;

static void Main(string[] args)
{

    myEvent += (s, e) => { Console.Write(s); };

    myEvent("a\n", null);   

}

第三种方法:(使用Lambda表达式)

delegate T AddDelegate<T>(T a, T b);

static void Main(string[] args)
{

  AddDelegate<string> add = (a, b) => a + b;
  Console.WriteLine(add("Lambda", "Expression"));

}

第四种方法:(第三种方法的通俗更改)

delegate string UseDelegate(string a, string b);

static void Main(string[] args)
{

  UseDelegate use = (a, b) => a + b;
  Console.WriteLine(use("Lambda", "Expression"));

}

以上方法分别使用了匿名代理和Lambda表达式来实现同样的功能,可以明显看出Lambda表达式的实现更为简洁。我们在使用Lambda表达式编写事件处理代码时,无需指明事件参数的类型,且返回值就是最后一条语句的执行结果。

top

第七个特性:扩展方法

当我们需要对已有类的功能进行扩展时,我们通常会想到继承,继承已有类,然后为其加入新的行为。

而C# 3.0中加入的扩展方法特性,则提供了另一种实现功能扩展的方式,我们可以在不使用继承的前提下实现对已有类本身的扩展,这种方法并不会产生新的类型,而是采用向已有类中加入新方法的方式来完成功能扩展。

在对已有类进行扩展时,我们需将所有扩展方法都写在一个静态类中,这个静态类就相当于存放扩展方法的容器,所有的扩展方法都可以写在这里面。而且扩展方法采用一种全新的声明方式:public static 返回类型 扩展方法名(this 要扩展的类型 sourceObj [,扩展方法参数列表]),与普通方法声明方式不同,扩展方法的第一个参数以this关键字开始,后跟被扩展的类型名,然后才是真正的参数列表。(第二个参数开始不需要使用this关键字)

static class Extensions 

{
  public static int ToInt32(this string source)
  {
    return Int32.Parse(source); 
  }
  public static T[] Slice<T>(this T[] source, int index, int count)
  {
    if (index < 0 || count < 0 || index + count > source.Length)
    {
      throw new ArgumentException();
    }
    T[] result = new T[count];
    Array.Copy(source, index, result, 0, count);
    return result;
  }
}

static void Main(string[] args)
{

  string number = "123";
  Console.WriteLine(number.ToInt32());
  int[] intArray = new int[] { 1, 2, 3 };
  intArray = intArray.Slice(1, 2);
  foreach (var i in intArray)
  {
    Console.WriteLine(i);
  }

}

在上面的示例中,静态的Extensions类中有两个扩展方法,第一个方法是对string类的扩展,它为string类加入了名为ToInt32的方法,该方法没有参数,并返回一个int类型的值,它将完成数字字符向整数的转换。有了这个扩展方法之后,就可对任意string类的对象调用ToInt32方法了,该方法就像其本身定义的一样。

第二个扩展方法是一个泛型方法,它是对所有数组类型的扩展,该方法完成数组的切片操作。   

C# 3.0中的Linq表达式,就是大量运用扩展方法来实现数据查询的。

top

第八个特性:Linq查询表达式

 C# 3.0中加入的最为复杂的特性就是Linq查询表达式了,这使我们可直接采用类似于SQL的语法对集合进行查询,这就使我们可以享受到关系数据查询的强大功能。

Linq查询表达式是建立在多种C# 3.0的新特性之上的,这也是我为什么最后才介绍Linq的原因。

var persons = new[]
{
  new { Name="Van's", Sex=false, Age=22 },
  new { Name="Martin", Sex=true, Age=30 },
  new { Name="Jerry", Sex=false, Age=24 },
  new { Name="Brog", Sex=false, Age=25 },
  new { Name="Vicky", Sex=true, Age=20 }
};
/*   执行简单Linq查询   
* 检索所有年龄在24岁以内的人   
* 查询结果放在results变量中   
* results变量的类型与数组persons相同
*/
var results = from p in persons where p.Age <= 24 select p;
foreach (var person in results)
{
  Console.WriteLine(person.Name);
}
// 定义匿名数组customers, 并为其赋初值   
// 该数组是匿名类型的
var customers = new[]
{
  new
  {
    Name = "Van's", City = "China", Orders = new[]
    {
      new { OrderNo = 0, OrderName = "C#", OrderDate = new DateTime(2007, 9, 5) },
      new { OrderNo = 1, OrderName = "Head ", OrderDate = new DateTime(2007, 9, 15) },
      new { OrderNo = 2, OrderName = "ASP", OrderDate = new DateTime(2007, 09, 18) },
      new { OrderNo = 3, OrderName = "C++", OrderDate = new DateTime(2002, 9, 20) }
    }
  },
  new
  {
    Name = "Brog", City = "China", Orders = new[]
    {
      new { OrderNo = 0, OrderName = "C#", OrderDate = new DateTime(2007, 9, 15) }
    }
  },
  new
  {
    Name = "Vicky", City = "London", Orders = new[]
    {

      new { OrderNo = 0, OrderName = "C++", OrderDate = new DateTime(2007, 9, 20) }
    }
  }
};
/* 执行多重Linq查询   
* 检索所在城市为中国, 且订单日期为2007年以后的所有记录   
* 查询结果是一个匿名类型的数组   
* 其中包含客户名, 订单号, 订单日期, 订单名四个字段   
*/
var someCustomers = from c in customers where c.City == "China"
                                from o in c.Orders where o.OrderDate.Year >= 2007
                                select new { c.Name, o.OrderNo, o.OrderDate, o.OrderName };   
foreach (var customer in someCustomers)   
{   
  Console.WriteLine( customer.Name + ", "+customer.OrderNo+", " + customer.OrderName + ", " + customer.OrderDate.ToString("D") );
}

top

转载于:https://www.cnblogs.com/ienuu1314/archive/2010/12/14/1905662.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值