C#语言的改进
自动属性
利用自动属性,可以用简化的语法声明属性,C#编译器会自动添加未键入的内容
编译器会声明一个用于存储属性的私有字段,并在属性的get和set块中使用该字段
public int MyProp
{
get;
set;
}
使用自动属性时,只能通过属性访问数据,不能通过底层的私有字段访问,因为我们不知道底层私有字段的名称
自动属性必须包含get和set访问块,无法使用这种方式定义只读或只写属性
对象初始化器
实例化对象时,要为每个需初始化的,可公开访问的属性或字段使用名-值对,来提供其值
<className> <variableName>=new <className>
{
<propertyOrField1>=<value1>,
<propertyOrField2>=<value2>,
……
<propertyOrFieldN>=<valueN>
}
public class Curry
{
public String MainIngredient { get; set; }
public String Style { get; set; }
public String Spiciness { get; set; }
}
Curry tastyCurry=new Curry( );
tastyCurry.MainIngredient=“panir tikka”;
tastyCurry.Style=“jalfrezi”;
tastyCurry.Spiciness=18;
如果类定义中未包含构造函数,这段代码就使用C#编译器提供的默认无参数构造函数
为了简化这个初始化过程,可以提供一个合适的非默认构造函数
public class Curry
{
public Curry(string mainIngredient, string style, int spiciness)
{
MainIngredient=mainIngredient;
Style=style;
Spiciness=spiciness;
}
……
}
Student sdt=new Student
{
Name=“Mary”,
Age=30,
Sex=“女”
};
类型推理
var =;
变量隐式地类型化为value的类型
如果编译器不能确定var声明的变量类型,代码就不会编译。因此,在用var声明变量时,必须同时初始化该变量,因为如果没有初始值,编译器就不能确定变量的类型
var myVar=5;
var myArray=new[] {3,4,5};
初始化器使用的数组元素必须是以下情形的一种
相同的类型
相同的引用类型或空
所有元素的类型都可以隐式地转换为一个类型
var myArray=new[] {3,”not an int”,5};
不会编译
匿名类型
var stu = new
{
Name = "Mary",
Age = 32,
Sex = "女"
};
匿名类型在内部有一个标识符,但不能在代码中使用
如果要在数据存储对象中修改属性的值,就不能使用匿名类型
动态类型
动态变量是类型不固定的变量
仅在编译期间存在,在运行期间会被System.Object代替
dynamic myDynamicVar;
高级方法参数
有些方法有大量的参数,许多参数并不是每次调用都需要的
可选参数
public List<String> GetWords(String sentence, bool capitalizeWords)
{
……
}
public List<String> GetWords(String sentence)
{
return GetWords(sentence,false);
}
p.GetWords("hello,students", false);
Lambda表达式与匿名方法
匿名方法
匿名方法纯粹是为了委托目的而创建的
delegate (parameters)
{
……
};
Lambda表达式的组成
放在括号中的参数列表
=>运算符
C#语句或表达式
编译器会提取这个Lambda表达式,创建一个匿名方法,Lambda表达式和匿名方法会被编译为相同或相似的CIL代码
Lambda表达式的参数
隐式参数(a,b)=>a+b
显式参数(int a,int b)=>a+b
不能在同一个Lambda表达式中同时使用显式的
和隐式地参数类型
如果只有一个参数,可省略括号
Lambda表达式的语句体
PerformOperations((a,b)=>a+b); 可改写为
PerformOperations(delegate(a,b)=>
{
return a+b;
});
PerformOperations((a,b)=>
{
return a+b;
});
yield
yield
C# 2.0添加了yield语句,以便于创建枚举器
yield return返回集合的一个元素,并移动到下一个元素上
yield break可停止迭代
yield语句会生成一个迭代器,而不仅仅生成一个包含的项的列表。这个枚举器通过foreach语句调用。从foreach中依次访问每一项时,就会访问枚举器。这样可以大大减少迭代大量的数据,而无需一次把所有的数据都读入内存
包含yield语句的方法或属性也称为迭代块,迭代块必须声明为返回IEnumerator或IEnumerable接口,或者这些接口的泛型版本。这个块可以包含多条yield return语句或yield break语句,但不能包含return语句
使用迭代块,编译器会生成一个yield类型,其中包含一个状态机
yield类型实现IEnumerator和IDisposable接口的属性和方法
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
namespace{
class Program
{
static void Main(string[] args)
{
HelloCollection helloCollection = new HelloCollection();
foreach (string s in helloCollection)
{
Console.WriteLine(s);
}
Console.ReadKey();
}
}
//以下是使用yield和不使用yield
//public class HelloCollection : IEnumerable
//{
// public IEnumerator GetEnumerator()
// {
// yield return "Hello";
// yield return "World";
// }
//}
public class HelloCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
Enumerator enumerator = new Enumerator(0);
return enumerator;
}
public class Enumerator : IEnumerator, IDisposable
{
private int state;
private object current;
public Enumerator(int state)
{
this.state = state;
}
public bool MoveNext()
{
switch (state)
{
case 0:
current = "Hello";
state = 1;
return true;
case 1:
current = "World";
state = 2;
return true;
case 2:
break;
}
return false;
}
public void Reset()
{
throw new NotSupportedException();
}
public object Current
{
get { return current; }
}
public void Dispose()
{
}
}
}
}