华易动力天津网站制作公司 免费咨询热线:400-0022-823 电话:022-28261501 28335110
地址:天津市河西区围堤道146号华盛广场B座22楼
点击这里给我发消息  点击这里给我发消息  点击这里给我发消息
  首页 关于我们 建网站:从这里开始 域名空间服务 案例展示 新闻中心 网站制作知识 网站设计技巧 人才招聘 联系我们  
  网站制作知识
程序制作
数据库知识
域名空间知识
SEO网站优化
天津网站制作方案 更多..
如何获得了大量的好的外链资源
常见的长尾关键词组合方法
如何利用百度平台获取流量
营销优化型网站的简介
新顶级域名的形式
网站建设分为如下八步
网站专题设计
关于门户网站设计方案
华易动力售后服务规范
服务器机房介绍
优秀客户展示(排名无先后) 更多..
环化(天津)燃气设备安装有限公司
天津市国信投资担保有限公司
天津城市职业学院
天津大学EMBA
南开大学CID
北京同仁堂天津药店有限公司
金权道(天津)餐饮管理有限公司
天津市友好合作城市企业促进会
天津天大求实电力新技术股份有限公司
天津红旗农贸投资控股有限公司
天津二人锅餐饮管理有限公司
天津市滨湖剧院
渤海产业投资基金管理有限公司
天津天富软管工业有限公司
新闻中心-行业资讯 更多..
· 企业为什么要做APP   2016-11-24
· 如何搭配网站   2016-11-16
· css表单布局的五个小技巧   2016-11-16
· 服务器维护的重点   2016-11-14
· 如何建设你想要的网站类型   2016-11-14
· 阿里设计师用这2方法提升设计创新力   2016-11-3
· 我们看过的各种设计理论法则   2016-11-3
· Windows 8设计时的安全性   2013-12-27
· 未来网站技术的发展   2013-10-12
· 企业网站建设规划   2013-7-30
全部信息 当前位置:首页网站制作知识 → 详细内容
.net3.0特性介绍
更新时间:2012/7/31 点击:1150次

隐式类型化本地变量

  这个特性非常简单,有些JavaScript的影子,我们可以统一使用使用"var"关键字来声明局部变量,而不再需要指明变量的确切类型了,变量的确切类型可通过声明变量时的初始值推断出来。这样一来,可以大大简化我们声明局部变量的工作量了,下面是一个例子:
  class LocalVariables : AppRunner.AbstractApplication
  {
  public override void Run()
  {
  var intValue = 5;
  var stringValue = "This is a string";
  var customClass = new LocalVariables();
  var intArray = new int[3] { 1,2,3 };
  foreach (var value in intArray)
  Console.WriteLine(value);
  }
  }
  上面的代码将被解析成:
  class LocalVariables : AppRunner.AbstractApplication
  {
  public override void Run()
  {
  int intValue = 5;
  string stringValue = "This is a string";
  LocalVariables customClass = new LocalVariables();
  int[] intArray = new int[3];
  foreach (int value in intArray)
  Console.WriteLine(value);
  }
  }
  要特别注意的是,由于变量的类型是通过变量初始值推断而来的,所以在声明变量的同时必需为变量指定初始值。并且,变量并不是没有类型的,变量一旦初始化之后,类型就确定下来了,以后就只能存储某种类型的值了,比如上面的stringValue的类型经推断为string,所以该变量就只能保存string类型的值了。

匿名类型

  有些时候我们需要临时保存一些运算的中间结果,特别是当这些中间结果是由多个部份组成时,我们常常会去声明一个新的类型,以方便保存这些中间结果。表面上看起来这很正常,而细想之后就会发现,这个新类型只服务于这个函数,其它地方都不会再使用它了,就为这一个函数而去定义一个新的类型,确实有些麻烦。
  现在,C#3.0中的匿名类型特性就可以很好的解决上面提到的问题,通过匿名类型,我们可以简单使用new { 属性名1=值1,属性名2=值2,.....,属性名n=值n }的形式直接在函数中创建新的类型,看下面这个例子:
  class AnonymousType : AppRunner.AbstractApplication
  {
  public override void Run()
  {
  var anonymousType1 = new {
  CardNumber = "10001",Name = "van’s",Sex = true
  };
  Console.WriteLine(anonymousType1.CardNumber);
  Console.WriteLine(anonymousType1.Name);
  var anonymousType2 = new {
  CardNumber = "10002",Name = "martin",Sex = true
  };
  anonymousType2 = anonymousType1;
  }
  }
  在新类型中只能有字段成员,而且这些字段的类型也是通过初值的类型推断出来的。如果在声明新的匿名类型时,新类型的字段名、顺序以及初始值的类型是一致的,那么将会产生相同的匿名类型,所以上例中anonymousType1和anonymousType2的类型是相同的,自然能进行anonymousType2=anonymousType1的赋值。

隐式类型化数组

  这个特性是对隐式类型化本地变量的扩展,有了这个特性,将使我们创建数组的工作变得简单。我们可以直接使用"new[]"关键字来声明数组,后面跟上数组的初始值列表。在这里,我们并没有直接指定数组的类型,数组的类型是由初始化列表推断出来的。
  class AnonymousTypeArray : AppRunner.AbstractApplication
  {
  public override void Run()
  {
  var intArray = new[] { 1,2,3,4,5 };
  var doubleArray = new[] { 3.14,1.414 };
  var anonymousTypeArray = new[] {
  new { Name="van’s",Sex=false,Arg=22 },
  new { Name="martin",Sex=true,Arg=23 }
  };
  Console.WriteLine(intArray);
  Console.WriteLine(doubleArray);
  Console.WriteLine(anonymousTypeArray[0].Name);
  }
  }
  上面的代码中,anonymousTypeArray变量的声明同时运用了隐式类型化数组和匿名类型两种特性,首先创建匿名类型,然后再初始值列表,推断出数组的确切类型。

对象构造者

  我们在声明数组时,可以同时对其进行初始化,这样就省去了很多麻烦,但是在创建类的对象时,这招可就不灵了,我们要么调用该类的构造函数完成对象的初始化,要么就手工进行初始化。这两种方法都不太方便,使用构造函数来对对象进行初始化时,我们为了某种灵活性,可能需要编写构造函数的多个重载版本,实在是麻烦。
  C#3.0中加入的对象构造者特性,使得对象的初始化工作变得格外简单,我们可以采用类似于数组初始化的方式来初始化类的对象,方法就是直接在创建类对象的表达式后面跟上类成员的初始化代码。具体示例如下:
  class Point
  {
  public int X { get; set; }
  public int Y { get; set; }
  public override string ToString()
  {
  return "(" + X.ToString() + "," + Y.ToString() + ")";
  }
  }
  class Rectangle
  {
  public Point P1 { get; set; }
  public Point P2 { get; set; }
  public Rectangle()
  {
  P1 = new Point();
  P2 = new Point();
  }
  public override string ToString()
  {
  return "P1: " + P1 + ",P2: " + P2;
  }
  }
  class ObjectBuilder : AppRunner.AbstractApplication
  {
  public override void Run()
  {
  Point thePoint = new Point() { X = 1,Y = 2 };
  Console.WriteLine("Point(X,Y) = ",thePoint);
  Rectangle theRectangle = new Rectangle() {
  P1 = { X = 1,Y = 1 },P2 = { X = 100,Y = 200 }
  };
  Console.WriteLine(theRectangle);
  }
  }
  我们在定义Point类的X和Y属性时,只须写上该属性的get和set访问器声明,C#编译器会自动为我们生成默认的get和set操作代码,当我们需要定义简单属性时,这个特性非常有用。
  我们以new Point() { X = 1,Y = 2 }语句,轻松的完成了对Point类的初始化工作。在创建类的对象时,我们可以按照需要去初始化类的对象,只要在类的创建表达式后跟上要初始化属性的列表即可,且可以只对需要初始化的属性赋初值,而无需把所有属性的初始值都写上去。
  在theRectangle对象的初始化表达式中,我们首先对P1属性进行初始化,然而P1属性也是一个自定义的类型,所以P1属性的初始化是另一个类型(Point)的初始化表达式,我们可以这样的方式来对更加复杂的类型进行初始化。
  上篇文章中介绍了C# 3.0中比较简单的四个特性,分别是隐式类型化本地变量、匿名类型、隐式类型化数组,以及对象构造者,下面我将对C# 3.0中的较复杂,同时也是非常强大的几个特性进行介绍,供大家快速浏览。

集合构造者

  我们可以在声明数组的同时,为其指定初始值,方法是直接在数组声明的后面跟上初始值列表。这样就使数组的初始化工作变得简单,而对于我们自己创建的集合类型,就无法享受到与普通数组一样的待遇了,我们无法在创建自定义集合对象的同时,使用数组的初始化语法为其指定初始值。
  C# 3.0中加入的集合构造者特性,可使我们享受到与普通数组一样的待遇,从而在创建集合对象的同时为其指定初始值。为了做到这一点,我们需要让我们的集合实现ICollection<T>;接口,在这个接口中,完成初始化操作的关键在于Add函数,当我使用初始化语法为集合指定初始值时,C#编译器将自动调用ICollection<T>;中的Add函数将初始列表中的所有元素加入到集合中,以完成集合的初始化操作。使用示例如下:
  class CollectionInitializer : AppRunner.AbstractApplication
  {
  class StringCollection : ICollection<string>
  {
  public void Add(string item)
  {
  Console.WriteLine(item);
  }
  // Other ICollection<T> Members
  }
  public override void Run()
  {
  StringCollection strings = new StringCollection() { "Van's","Brog","Vicky" };
  }
  }
  在这个示例中,编译器会自动为strings对象调用Add方法,以将初始值列表中的所有元素加入到集合中,这里我们只是简单将初始值列表中的元素输出到控制台。

Lambda表达式

  C# 2.0中加入的匿名代理,简化了我们编写事件处理函数的工作,使我们不再需要单独声明一个函数来与事件绑定,只需要使用delegate关键字在线编写事件处理代码。
  而C# 3.0则更进一步,通过Lambda表达式,我们可以一种更为简洁方式编写事件处理代码,新的Lambda事件处理代码看上去就像一个计算表达式,它使用"=>"符号来连接事件参数和事件处理代码。我可以这样写:SomeEvent += 事件参数 => 事件处理代码;下面是完整的示例:
  delegate T AddDelegate<T>(T a,T b);
  class LambdaExpression : AppRunner.AbstractApplication
  {
  public static event EventHandler MyEvent;
  public override void Run()
  {
  MyEvent += delegate(object s,EventArgs e)
  {
  Console.WriteLine(s);
  };
  MyEvent += (s,e) => { Console.WriteLine(s); };
  MyEvent(this,null);
  AddDelegate<string> add = (a,b) => a + b;
  Console.WriteLine(add("Lambda","Expression"));
  }
  }
  在上面的例子中,分别使用了匿名代理和Lambda表达式来实现同样的功能,可以明显看出Lambda表达式的实现更为简洁。我们在使用Lambda表达式编写事件处理代码时,无需指明事件参数的类型,且返回值就是最后一条语句的执行结果。

扩展方法

  当我们需要对已有类的功能进行扩展时,我们通常会想到继承,继承已有类,然后为其加入新的行为。而C# 3.0中加入的扩展方法特性,则提供了另一种实现功能扩展的方式,我们可以在不使用继承的前提下实现对已有类本身的扩展,这种方法并不会产生新的类型,而是采用向已有类中加入新方法的方式来完成功能扩展。
  在对已有类进行扩展时,我们需将所有扩展方法都写在一个静态类中,这个静态类就相当于存放扩展方法的容器,所有的扩展方法都可以写在这里面。而且扩展方法采用一种全新的声明方式:public static 返回类型 扩展方法名(this 要扩展的类型 sourceObj [,扩展方法参数列表]),与普通方法声明方式不同,扩展方法的第一个参数以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;
  }
  }
  class ExtensionMethods : AppRunner.AbstractApplication
  {
  public override void Run()
  {
  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表达式,就是大量运用扩展方法来实现数据查询的。

Linq查询表达式

  C# 3.0中加入的最为复杂的特性就是Linq查询表达式了,这使我们可直接采用类似于SQL的语法对集合进行查询,这就使我们可以享受到关系数据查询的强大功能。
  Linq查询表达式是建立在多种C# 3.0的新特性之上的,这也是我为什么最后才介绍Linq的原因。下面看一个例子:
  class LinqExpression : AppRunner.AbstractApplication
  {
  public override void Run()
  {
  // 定义匿名数组persons,并为其赋初值
  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);
  }
  Console.WriteLine();
  // 定义匿名数组customers,并为其赋初值
  // 该数组是匿名类型的
  var customers = new[] {
  new {
  Name="Van's",City="China",Orders=new[] {
  new {
  OrderNo=0,
  OrderName="C# Programming Language(Second Edition)",
  OrderDate=new DateTime(2007,9,5)
  },
  new {
  OrderNo=1,
  OrderName="Head First Design Patterns(Chinese Edition)",
  OrderDate=new DateTime(2007,9,15)
  },
  new {
  OrderNo=2,
  OrderName="ASP.NET Unleashed 2.0(Chinese Edition)",
  OrderDate=new DateTime(2007,09,18)
  },
  new {
  OrderNo=3,
  OrderName="The C++ Programming Langauge(Special Edition)",
  OrderDate=new DateTime(2002,9,20)
  }
  }
  },
  new {
  Name="Brog",City="China",Orders=new[] {
  new {
  OrderNo=0,
  OrderName="C# Programming Language(Second Edition)",
  OrderDate=new DateTime(2007,9,15)
  }
  }
  },
  new {
  Name="Vicky",City="London",Orders=new[] {
  new { OrderNo=0,
  OrderName="C++ Programming Language(Special Edition)",
  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.OrderName + "," +
  customer.OrderDate.ToString("D")
  );
  }
  }
  }
  从上面的例子中,我们可以看到Linq查询的强大特性,它允许我们进行简单查询,或者进行更为复杂的多重连接查询。且查询的结果还可以是自定义的匿名类型。
 
  公司总机:022-28261501 28335110
客户服务邮箱:service@nfree.cn,手机直线:15822335163
CopyRight 2006~2024 All Rights Reserved 天津市华易动力信息科技有限公司
地址:天津市河西区围堤道146号华盛广场B座22楼 邮编:300202

津公网安备 12010302001042号


在线QQ(售前咨询)
点击这里给我发消息  点击这里给我发消息  点击这里给我发消息