LINQ教程Word文件下载.docx
《LINQ教程Word文件下载.docx》由会员分享,可在线阅读,更多相关《LINQ教程Word文件下载.docx(24页珍藏版)》请在冰豆网上搜索。
你不能用var关键字声明一个变量而不给它赋值
因为编译器无法推导出你这个变量是什么类型的。
2.匿名类型
创建一个对象,一定要先定义这个对象的类型吗?
不一定的!
来看看这段代码
(2)使用
varobj=new{Guid.Empty,myTitle="
匿名类型"
myOtherParam=newint[]{1,2,3,4}};
Console.WriteLine(obj.Empty);
//另一个对象的属性名字,被原封不动的拷贝到匿名对象中来了。
Console.WriteLine(obj.myTitle);
Console.ReadKey();
new关键字之后就直接为对象定义了属性,并且为这些属性赋值
而且,对象创建出来之后,在创建对象的方法中,还可以畅通无阻的访问对象的属性
当把一个对象的属性拷贝到匿名对象中时,可以不用显示的指定属性的名字,这时原始属性的名字会被“拷贝”到匿名对象中
(3)注意
如果你监视变量obj,你会发现,obj的类型是AnonymousType类型的
不要试图在创建匿名对象的方法外面去访问对象的属性!
(4)优点
这个特性在网站开发中,序列化和反序列化JSON对象时很有用
3.自动属性
为一个类型定义属性,我们一般都写如下的代码:
publicclassMyObj2
{
privateGuid_id;
privatestring_Title;
publicGuidid
get{return_id;
}
set{_id=value;
}
}
publicstringTitle
get{return_Title;
set{_Title=value;
但很多时候,这些私有变量对我们一点用处也没有,比如对象关系映射中的实体类。
自C#3.0引入了自动实现的属性,
以上代码可以写成如下形式:
(2)使用
publicclassMyObj
publicGuidid{get;
set;
publicstringTitle{get;
这个特性也和var关键字一样,是编译器帮我们做了工作,不会影响性能的
4.初始化器
我们创建一个对象并给对象的属性赋值,代码一般写成下面的样子
varmyObj=newMyObj();
myObj.id=Guid.NewGuid();
myObj.Title="
allen"
自C#3.0引入了对象初始化器,
代码可以写成如下的样子
(2)使用
varmyObj1=newMyObj(){id=Guid.NewGuid(),Title="
};
如果一个对象是有参数的构造函数
那么代码看起来就像这样
varmyObj1=newMyObj("
){id=Guid.NewGuid(),Title="
集合初始化器的样例代码如下:
vararr=newList<
int>
(){1,2,3,4,5,6};
(3)优点
我个人认为:
这个特性不是那么amazing,
这跟我的编码习惯有关,集合初始化器也就罢了,
真的不习惯用对象初始化器初始化一个对象!
5.委托
(1)使用
我们先来看一个简单的委托代码
delegateBooleanmoreOrlessDelgate(intitem);
classProgram
staticvoidMain(string[]args)
vararr=newList<
(){1,2,3,4,5,6,7,8};
vard1=newmoreOrlessDelgate(More);
Print(arr,d1);
Console.WriteLine("
OK"
);
vard2=newmoreOrlessDelgate(Less);
Print(arr,d2);
Console.ReadKey();
staticvoidPrint(List<
arr,moreOrlessDelgatedl)
foreach(variteminarr)
if(dl(item))
Console.WriteLine(item);
staticboolMore(intitem)
if(item>
3)
{
returntrue;
returnfalse;
staticboolLess(intitem)
if(item<
这段代码中
<
1>
首先定义了一个委托类型
delegateBooleanmoreOrlessDelgate(intitem);
你看到了,委托和类是一个级别的,确实是这样:
委托是一种类型
和class标志的类型不一样,这种类型代表某一类方法。
这一句代码的意思是:
moreOrlessDelgate这个类型代表返回值为布尔类型,输入参数为整形的方法
2>
有类型就会有类型的实例
vard1=newmoreOrlessDelgate(More);
vard2=newmoreOrlessDelgate(Less);
这两句就是创建moreOrlessDelgate类型实例的代码,
它们的输入参数是两个方法
3>
有了类型的实例,就会有操作实例的代码
Print(arr,d1);
Print(arr,d2);
我们把前面两个实例传递给了Print方法
这个方法的第二个参数就是moreOrlessDelgate类型的
在Print方法内用如下代码,调用委托类型实例所指向的方法
dl(item)
6.泛型
(1)为什么要有泛型
假设你是一个方法的设计者,
这个方法有一个传入参数,有一个返回值。
但你并不知道这个参数和返回值是什么类型的,
如果没有泛型,你可能把参数和返回值的类型都设定为Object了
那时,你心里肯定在想:
反正一切都是对象,一切的基类都是Object
没错!
你是对的!
这个方法的消费者,会把他的对象传进来(有可能会做一次装箱操作)
并且得到一个Object的返回值,他再把这个返回值强制类型转化为他需要的类型
除了装箱和类型转化时的性能损耗外,代码工作的很好!
那么这些新能损耗能避免掉吗?
有泛型之后就可以了!
使用简单的泛型
先来看下面的代码:
varintList=newList<
(){1,2,3};
intList.Add(4);
intList.Insert(0,5);
foreach(variteminintList)
{
Console.WriteLine(item);
}
Console.ReadKey();
在上面这段代码中我们声明了一个存储int类型的List容器
并循环打印出了容器里的值
注意:
如果这里使用Hashtable、Queue或者Stack等非泛型的容器
就会导致装箱操作,损耗性能。
因为这些容器只能存储Object类型的数据
泛型类型
List<
T>
、Dictionary<
TKey,TValue>
等泛型类型都是.net类库定义好并提供给我们使用的
但在实际开发中,我们也经常需要定义自己的泛型类型
来看下面的代码:
publicstaticclassSomethingFactory<
{
publicstaticTInitInstance(TinObj)
if(false)//你的判断条件
//dowhatyouwant...
returninObj;
}
returndefault(T);
default为泛型代码中的默认关键字
给定参数化类型T的一个变量t,只有当T为引用类型时,语句t=null才有效;
只有当T为数值类型而不是结构时,语句t=0才能正常使用。
解决方案是使用default关键字,此关键字对于引用类型会返回空,对于数值类型会返回零。
对于结构,此关键字将返回初始化为零或空的每个结构成员,具体取决于这些结构是值类型还是引用类型。
这段代码的消费者如下:
vara1=SomethingFactory<
.InitInstance(12);
Console.WriteLine(a1);
//Console.ReadKey();
是等待键盘输入,退出程序。
使调试时能看到输出结果。
如果没有此句,命令窗口会一闪而过。
输出的结果为0
这就是一个自定义的静态泛型类型,
此类型中的静态方法InitInstance对传入的参数做了一个判断
如果条件成立,则对传入参数进行操作之后并把它返回
如果条件不成立,则返回一个空值
[1]
传入参数必须为指定的类型,
因为我们在使用这个泛型类型的时候,已经规定好它能接收什么类型的参数
但在设计这个泛型的时候,我们并不知道使用者将传递什么类型的参数进来
[2]
如果你想返回T类型的空值,那么请用default(T)这种形式
因为你不知道T是值类型还是引用类型,所以别擅自用null
泛型约束
很多时候我们不希望使用者太过自由
我们希望他们在使用我们设计的泛型类型时
不要很随意的传入任何类型
对于泛型类型的设计者来说,要求使用者传入指定的类型是很有必要的
因为我们只有知道他传入了什么东西,才方便对这个东西做操作
让我们来给上面设计的泛型类型加一个泛型约束
代码如下:
publicstaticclassSomethingFactory<
whereT:
MyObj
这样在使用SomethingFactory的时候就只能传入MyObj类型或MyObj的派生类型啦
还可以写成这样
whereT:
MyObj,new()
来约束传入的类型必须有一个构造函数。
(3)泛型的好处
算法的重用
想想看:
list类型的排序算法,对所有类型的list集合都是有用的
类型安全
提升性能
没有类型转化了,一方面保证类型安全,另一方面保证性能提升
4>
可读性更好
这一点就不解释了
7.泛型委托
委托需要定义delgate类型
使用起来颇多不便
而且委托本就代表某一类方法
开发人员经常使用的委托基本可以归为三类,
哪三类呢?
请看下面:
Predicate泛型委托
把上面例子中d1和d2赋值的两行代码改为如下:
//vard1=newmoreOrlessDelgate(More);
vard1=newPredicate<
(More);
//vard2=newmoreOrlessDelgate(Less);
vard2=newPredicate<
(Less);
把Print方法的方法签名改为如下:
//staticvoidPrint(List<
arr,moreOrlessDelgate<
dl)
arr,Predicate<
然后再运行方法,控制台输出的结果和原来的结果是一模一样的。
那么Predicate到底是什么呢?
来看看他的定义:
//摘要:
//表示定义一组条件并确定指定对象是否符合这些条件的方法。
//
//参数:
//obj:
//要按照由此委托表示的方法中定义的条件进行比较的对象。
//类型参数:
//T:
//要比较的对象的类型。
//返回结果:
//如果obj符合由此委托表示的方法中定义的条件,则为true;
否则为false。
publicdelegateboolPredicate<
inT>
(Tobj);
看到这个定义,我们大致明白了。
.net为我们定义了一个委托,
这个委托表示的方法需要传入一个T类型的参数,并且需要返回一个bool类型的返回值
有了它,我们就不用再定义moreOrlessDelgate委托了,
而且,我们定义的moreOrlessDelgate只能搞int类型的参数,
Predicate却不一样,它可以搞任意类型的参数
但它规定的还是太死了,它必须有一个返回值,而且必须是布尔类型的,同时,它必须有一个输入参数
除了Predicate泛型委托,.net还为我们定义了Action和Func两个泛型委托
Action泛型委托
Action泛型委托限制的就不那么死了,
他代表了一类方法:
可以有0个到16个输入参数,
输入参数的类型是不确定的,
但不能有返回值,
来看个例子:
vard3=newAction(noParamNoReturnAction);
vard4=newAction<
int,string>
(twoParamNoReturnAction);
尖括号中int和string为方法的输入参数
staticvoidnoParamNoReturnAction()
//dowhatyouwant
staticvoidtwoParamNoReturnAction(inta,stringb)
Func泛型委托
为了弥补Action泛型委托,不能返回值的不足
.net提供了Func泛型委托,
相同的是它也是最多0到16个输入参数,参数类型由使用者确定
不同的是它规定要有一个返回值,返回值的类型也由使用者确定
如下示例:
vard5=newFunc<
(oneParamOneReturnFunc);
string类型(最后一个泛型类型)是方法的返回值类型
staticstringoneParamOneReturnFunc(inta)
returnstring.Empty;
8.匿名方法
在上面的例子中
为了得到序列中较大的值
我们定义了一个More方法
vard1=newPredicate<
然而这个方法,没有太多逻辑(实际编程过程中,如果逻辑较多,确实应该独立一个方法出来)
那么能不能把More方法中的逻辑,直接写出来呢?
C#2.0之后就可以了,
请看下面的代码:
(2)使用
vararr=newList<
(){1,2,3,4,5,6,7,8};
//vard1=newmoreOrlessDelgate(More);
//vard1=newPredicate<
vard1=newPredicate<
(delegate(intitem)
{
//可以访问当前上下文中的变量
Console.WriteLine(arr.Count);
if(item>
returntrue;
returnfalse;
});
Print(arr,d1);
Console.WriteLine("
我们传递了一个代码块给Predicate的构造函数
其实这个代码块就是More函数的逻辑
(3)好处
代码可读性更好
可以访问当前上下文中的变量
这个用处非常大,
如果我们仍旧用原来的More函数
想要访问arr变量,势必要把arr写成类级别的私有变量了
用匿名函数的话,就不用这么做了。
9.Lambda表达式
.net的设计者发现在使用匿名方法时,
仍旧有一些多余的字母或单词的编码工作
比如delegate关键字
于是进一步简化了匿名方法的写法
List<
arr=newList<
(){1,2,3,4,5,6,7};
arr.ForEach(newAction<
(delegat