C#3.0特性总结
1:隐式类型的本地变量和数组
2:对象初始值设定项
3:集合初始值设定项
4:自动实现属性
5:匿名类型
6:扩展方法
7:分部方法定义
8:Lambda 表达式
关键字(var)
1:var可以用局部变量声明不可以用于字段可以应用于for、foreach、using语句中
2:var关键字不能包含自身对象或者集合初始化器,但可以经过new的新表达式
例:var result;//编译错误
var result=result+1;//编译错误
var result={1,2,3};//编译错误
3:var是推断类型,不是显示类型
4:var关键字指示编译器根据初始化语句右侧的表达式推断变量的类型
5:推断类型可以是内置类型、匿名类型、用户定义类型、.NET Framework 类库中定义的类型或任何表达式
注:var关键字并不意味着“变体”,也不表示该变量时松散类型化变量或后期绑定变量。它只是表示由编译器确定和分配最适合的类型
var 使用的场景
1:局部变量
例:var i = 5;
2:在for初始化语句
例:for(var i = 1; i < 10; ++i)
3:在foreach初始化语句
例:foreach(var item in list)
4:在using语句
例:using(var file = new StreamReader("C:\"))
一:隐式类型的本地变量和数组
注:隐形数组使用var关键字和数组初始化器创建。元素的数据类型必须能够隐式转换为同一数据类型,并且不能为空(null)
1:没有在初始化语句的左侧隐式类型的数组使用方括号
2:支持交错数组,不支持多维数组
例:var a = new [] {1,2,3} //一维数组
var b = new []
{
new [] {1,2,3},
new [] {5,6}
}; //交错数组
二:对象初始值设定项
注:对象初始化器由一系列成员对象组成,其对象必须初始化,用逗号间隔,使用{}封闭
1.NET 2.0写法:
User userInfo = new User();
userInfo.ID = “zhuxing”;
userInfo.Name = “czx”;
userInfo.Age= 22;
2.NET 3.5写法:
User userInfo = new User() {ID = “zhuxing”, Name = “czx”, Age=22};
注:嵌套复杂属性类型
User userInfo = new User()
{
ID=“zhuxing”,
Name=“czx”,
Address =new Address()
{
Province=“
City=“ningde”
}
};
1:可以和构造函数一起使用,并且构造函数初始化先于对象初始化器执行
2:允许部分赋值
3:允许给internal 成员赋值
public class user
{
public String Name { get; set; }
public String Age { get; set; }
private Int32 test = 25;
internal Int32 test2;
}
public class Program
{
static void
{
user person = new user { Name = "张三", Age = "男", test2 = 20 };
Console.WriteLine("{0},{1},{2}",person.Name, person.Age, person.test2);
Console.ReadLine();
}
}
//和构造函数一起使用
public class user
{
public String Name { get; set; }
public Int32 Age { get; set; }
private Int32 test = 25;
internal Int32 test2;
public user(Int32 Age)
{
this.Age = Age;
}
}
public class Program
{
static void
{
user person = new user(20) { Name = "张三", Age = 22, test2 = 20 };
Console.WriteLine("{0},{1},{2}",person.Name, person.Age, person.test2);
Console.ReadLine();
}
}
三:集合初始值设定项
注:
1:集合初始化器由一系列集合对象组成,用逗号间隔,使用{}封闭。
2:集合初始化器会对初始化器中的元素进行按序调用ICollection<T>.Add(T)方法
例如:List<int> number=new List<int>{1,2,3,4,5};
//集合初始化器
public class parame
{
public String Name { get; set; }
public Int32 Age { get; set; }
}
public class Program
{
static void
{
IList<parame> people = new List<parame>()
{
new parame{ Name = "张三", Age = 18},
new parame{ Name = "李四", Age = 20}
};
foreach (var i in people)//var 是3.0特有的
{
Console.WriteLine("{0},{1}", i.Name, i.Age);
}
Console.ReadLine();
}
}
四:自动实现属性
1、.NET2.0下写User类:
public class User
{
private string id;//用户ID
public string ID
{
get{return id;}
Set {id=value;}
}
private string name;//用户名称
public string Name
{
get{return name;}
set{name=value;}
}
}
2、.NET 3.5下写User类:
public class User
{
public string ID{get;set;}
public string Name{get;set;}
}
注:在VS2008像以上写法,编译器自动会为类中生成一个私有变量,并对这个变量实现公开的getter和setter访问器
五:匿名类型
注:使用new操作符和匿名对象初始化器创建一个新的对象,该对象是匿名类型的对象。
如:
var role=new{ID=“zhuxing”,Name=“czx”};
等同于:
class _Anonymous1
{
private string id;
public string ID
{
get{return id;}
set{id=value;}
}
private string name;
public string Name
{
get{return name;}
set{name=value;}
}
}
1:匿名类型提供了一种方便的方法,可以用来将一组只读属性封装到单个对象中,而无需首先显示定义一个类型
2:类型名由编译器生成,并且不能在源代码级使用
3:这些属性的类型由编译器判定
4:匿名类型通常用在查询表达式select子句中,以便返回源序列化对象的属性子集
5:匿名类型是使用new运算符和对象初始值设定项创建的
6:匿名类型是由一个或多个只读属性组成的类类型。不允许包含其他种类的类型
(如方法或事件)
7:匿名类型是直接从对象派生的引用类型。尽管应用程序无法访问匿名类型,但编译器仍会为其提供一个名称。
8:如果两个或更多个匿名类型以相同的顺序具有相同数量和种类的 如果两个或更多个匿名类型以相同的顺序具有相同数量和种类的属性,则编译器会将这些匿名类型视为相同的类型,并且它们共享编译器生成的相同类型信息。匿名类型具有方法范围 – 匿名类型具有方法范围。
9:匿名类型不能像属性一样包含不安全类型。
10:由于匿名类型上的 Equals 和 GetHashCode 方法是根据属性的 由于匿名类型上的Equals 和 GetHashCode 方法是根据属性的Equals 和 GetHashcode 定义的,因此仅当同一匿名类型的两个
注:查询表达式经常使用匿名类型,而这些类型只能使用对象初始值设定项进行初始化
例:var productInfos = from p in products
select new { p.ProductName, p.UnitPrice };
创建匿名类型时重命名字段:
select new {p.ProductName, Price = p.UnitPrice};
六:扩展方法
1、扩展方法的优势
1.1、允许开发人员往一个现有的CLR类型的公开契约(contract)中添加新的方法,而不用生成子类或者重新编译原来的类型。
1.2、可以通过使用实例方法语法调用的静态方法 ,对现有类功能进行扩充,从而使该类型的实例具有更多的方法(功能)。
1.3、允许我们在不改变源代码的情况下扩展(即添加不能修改)现有类型中的实例方法
1.4、有助于把今天动态语言中流行的对duck typing的支持之灵活性,与强类型语言之性能和编译时验证融合起来
2、扩展方法的要点
2.1、本质为将实例方法调用在编译期改变为静态类中的静态方法调用,具备静态方法的功能
2.2、作用域是整个namespace可见的,并且可以通过using namespace来导入其它命名空间中的扩展方法。
2.3、优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法
七:分部方法定义
注:处理一些轻量级的事件
八:Lambda 表达式
1、格式如下:(参数列表)=>表达式或语句块 ;
例: var str=list.FindAll(s=>s.indexof(“mzc”)>=0);
2、参数列表可以是显示或者隐式类型,在显式列表中,每个参数的类型是显式指定的,在隐式列表中,参数的类型由Lambda表达式出现的语境自动推断类型 。
例:
(x, y) => x * y;//多参数,隐式类型=>表达式
x => x * 10;//单参数,隐式类型=>表达式
x => { return x * 10; }; //单参数,隐式类型=>语句块
(int x) => x * 10;//单参数,显式类型=>表达式
(int x) => { return x * 10; };//单参数,显式类型=>语句块
( ) => Console.WriteLine(); //无参数
表达式树
注:表达式树允许像处理数据一样对Lambda表达式进行读取和改写,比如我们在动态查询的时候经常应用到