体验C#3.0
• 隐含类型局部变量
• 扩展方法
• 对象与集合初始化器
• 匿名类型
• Lambda表达式
• 查询表达式( LINQ )
• 表达式树
软件开发网 www.mscto.com
先来看看例句:
var i = 5;
var h=23.56;
var s = “C Sharp";
var intArr = new[] {1,2,3,4} ;
var a = new[] { 1, 10, 100, 1000 };
"var"这个关键字是不是很眼熟,javascript中经常用到(互相学习现在比较常见了),当然C#中var和javascript的var差别还是比较大。
1.var只能作为局部变量使用;
就是说var只能定义在一个方法里面,或者foreach,for,using等语句里面:
public class VarTest
{
private void test()
{
var i = 0;
}
}
2.var可以申明任何类型变量,可以根据后面的初始化语句自动推断类型;
这个和object有点像,但var是强类型,根据初始化表达式来定义变量的类型;
var i=0; i 是int类型
var str = "test"; str是string类型
3.var定义时,必须使用表达式初始化;
也就是必须定义成 var i=0; 没有初始化编译会报错,而且初始化值不能为null,编译器无法根据null来推断出局部变量的类型;初始值除了int,string等数据类型外,还可以使用new 一个对象作为初始值(从网上大家发表的看法,var使用最多的就是配合一个匿名类型的对象来使用,以及在Linq中使用)
配合匿名类型使用:
Console.WriteLine(a.Name);
Console.WriteLine(a.Age);在linq中应用:
var queryLowNums =
from num in numbers
where num < 5
select num;
foreach (var s in queryLowNums)
{
Console.Write(s.ToString() + " ");
}

4.var使用建议
一般var不要像“var i=9;”这样使用,程序可读性不高;
在匿名类型中使用比较方便;foreach中使用也不错;
var只是语言层面的东西,编译器会在编译的时候通过类型推断把它换成真正的类型
三.扩展方法
扩展方法定义如下:
public static void Foo(this string s) {
…
}
}
使用:
String s=“Hello,World”;
s.Foo();
我们以前会对一些参数、对象进行某些处理,而写一些独立方法来封装这些处理语句;这些方法为了方便重用,可能会写在一些公共类里供大家调用,例如:
public class PublicCenter
{
//传入参数为天数
public long GetDaysMin(int pDays)
{
return pDays * 24 * 60;
}
}
外部使用调用:
int days = 3;
PublicCenter pCenter = new PublicCenter();
int minutes = pCenter.GetDaysMin(days);
我想大家对上面这段代码的使用都非常熟悉,以前这样处理的情况非常的多!现在我们看看用扩展方法来处理会是怎么样;
public static class PublicCenter
{
//传入参数为天数(注意this关键字必不可少)
public static long GetDaysMin( this int pDays)
{
return pDays * 24 * 60;
}
}
外部使用调用:(注意静态类必须同在一个命名空间,或添加引用,这个大家应该也知道的(啰嗦))
int days = 3;
//当我们在所以int类型的变量后按下".",就会智能提示出这些自己写的扩展方法GetDaysMin()。
int minutes = days.GetDaysMin()
大家可以看出扩展方法的本质为将实例方法调用在编译期改变为静态类中的静态方法调用。
MSDN中对扩展方法的定义是:扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。
为什么使用扩展方法?
第一.使用方便:定义好某个类型的扩展方法后,只要是在这个类型后面点一个“.",就可以找到所有的扩展方法;而不用像以前先要找到方法所放的那个类,然后用通过调用该类的方法来实现;(很多时候,公共类库和实际调用是不同开发人员开发的,往往需要调用的人员不知道哪个类有哪些功能可以使用,这个在公共类库比较庞大的时候很麻烦)
第二.扩展方便:可以很方便的扩展底层类库,接口,第三方类库(控件,插件)等等,在上面添加我们需要的功能;而不需要我们重新修改这些底层类库,控件等(有很多时候这些东西我们根本没有办法更改,例如第三方提供的,非开源的);
扩展方法几种使用情况:
1.传递参数:
//this必须放第一个位置,后面传递参数类型没有限制
public static void Foo(this string s,string pName) {
…
}
}
使用:
String s=“Hello,World”;
s.Foo("maotin");
2.扩展方法的优先级:
注意扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法。
namespace Hongjun.Guo
{
public class MyClass
{
public void Print()
{
Console.WriteLine("****");
}
}
static class MyExtensionMethods
{
internal static void Print(this MyClass s)
{
Console.WriteLine("haha " + s.ToString());
}
}
}
调用范例:
using Hongjun.Guo;
static void Main(string[] args)
{
MyClass o = new MyClass();
o.Print();
Console.ReadLine();
}
这时候我们会看到何种结果呢??
答案:看到的是 ****
分析:
我们把上述两组代码编译后,再反编译成IL,我们就可以看到,实际上,扩展方法在IL层上是不存在的。
扩展方法实际是编译器调用某个类的某个方法的时候,先去这个类找,如果有这个方法,则就调用;如果找不到,根据引用的命名空间,再去找扩展方法(静态类的静态方法)。找到,就使用,找不到当然就编译错误了。
根据这个分析结果,我们就可以理解上述问题处理的结果了。
情况二: 扩展方法的嵌套
比如我们有如下扩展方法。
amespace Hongjun.Guo
{
static class MyExtensionMethods
{
public static int Test01(this int i)
{
return i * 3;
}
public static int Test02(this int i)
{
return i + 5;
}
}
}
下面是调用范例:
static void Main(string[] args)
{
int mm = 7;
Console.WriteLine(mm.Test01().Test02());
Console.WriteLine("*****");
Console.WriteLine(mm.Test02().Test01());
Console.WriteLine("*****");
Console.WriteLine(MyExtensionMethods.Test02(MyExtensionMethods.Test01(mm)));
Console.ReadLine();
}
问,调用的显示结果是何值?
答案: 依次显示: 26,36,26
分析:
mm.Test01().Test02()
这行代码编译后相当于如下代码:
MyExtensionMethods.Test02(MyExtensionMethods.Test01(mm))
这两行代码在编译后的IL中是完全一样的。
扩展方法冲突也是要考虑的问题,如果对同一个类定义了相同的扩展函数(方法名,参数都一样),在外面调用是就会产生调用不明确的编译问题,因此定义扩展方法也需要考虑是否冲突!
扩展方法提供了不错一种编程方式,在日常工作中应该会逐渐被引进,但是也有一些限制,目前体会还不是很深入,后期有新观点会不断补充!
扩展方法是一种编译时技术,注意与反射等运行时技术进行区别,并慎重使用。



