从C# 2.0 爬向 C# 4.0—— 让我们匿名吧——C# 是个优雅的语言
前言
开始时学的是C#2.0而且没有学完全。工作后,不是在忙着赶项目,就是对各种技术尝尝鲜,而语言的学习却没有什么进步。直到半年前开始入门Python(纯粹爱好,断断续续的学着)才发现——原来编程还可以这样!原来代码还可以这样写!
沉溺于各种设计模式、框架、新鲜技术
回眸一望
忽然发现
她
依然如此优雅
甚至
更胜从前!
目标
补完C# 2.0 3.0的新特性,然后在研究研究4.0,上一篇中对C# 的泛型进行了一下温习(泛型)。本篇要说说C#里的匿名 ,主要包括:匿名方法、匿名类型、隐式类型局部变量等。
参考链接
详细读完这些文章,你就不用看我写的了!如有不明请往下,还是不明请留言,大家相互讨论。
对象初始化
在匿名之前我们先说说对象的初始化。C# 为我们提供了对象初始化器 、集合初始化器和自动属性这几个利器,方便我们初始化一个对象。
class Program
{
static void Main(string[] args)
{
Cat mili = new Cat { Birthday=new DateTime (2010,3,3), Name = "mili" };
Cat kaka = new Cat("kaka") { Birthday = new DateTime(2008, 3, 3) };
Cat tutu = new Cat("tutu2") { Birthday = new DateTime(2010, 4, 3), Name = "tutu" };
Console.WriteLine("name:{0},Age:{1}", mili.Name, mili.Age);
Console.WriteLine("name:{0},Age:{1}", tutu.Name, tutu.Age);
List<Cat> CatShop = new List<Cat> {
new Cat { Birthday=new DateTime (2010,6,3), Name = "lulu" },
new Cat { Birthday=new DateTime (2010,8,3), Name = "xixi" },
new Cat { Birthday=new DateTime (2010,9,4), Name = "fafa" }
};
Console.Read();
}
}
class Cat
{
public string Name
{
get;
set;
}
public DateTime Birthday
{
get;
set;
}
public int Age
{
get
{
return DateTime.Now.Year - Birthday.Year;
}
}
/// <summary>
/// 如果需要使用到 构造函数,需要手动添加无参构造函数。
/// 其实在对象和集合初始化里,完全可以省略构造函数。
/// </summary>
public Cat() { }
public Cat(String name) { }
}
如果不需要其他的逻辑,自动实现的属性使属性的声明变得非常简洁,我们不用再在类内定义一个私有的变量做容器。事实上编译器会创建一个私有的匿名后备字段,该字段只能通过属性的 get 和 set 访问器进行访问(我们以前做的事情,编译器帮我们完成了)。 以声明方式初始化类型的对象即(new Cat{}),无需显式调用该类型的构造函数(例子里也有调用构造函数在初始化的,从打印结果可以看到,构造函数在初始化之前执行),就可以直接给对象的各属性赋值。不过需要注意的是,要确保类中无参构造函数的存在。
匿名类型与隐式类型的局部变量
Var ——隐式类型的局部变量,它可以在方法范围内的变量。隐式类型其实是强类型变量(就好像您已经声明该类型一样),它最终由编译器确定类型,它和javascript的弱类型是不一样的。编译器(前面的特性也都是它偷偷干的)会根据我们赋值的情况帮助我们确定Var 变量的类型。
var namei = new Cat { Name = "namei", Birthday = new DateTime(2005, 4, 3) };
var i = 13;
Console.WriteLine("name:{0},age:{1},NO:{2}", namei.Name, namei.Age, i);
//事实上我们经常这样用var
var lulu = new { Name = "lulu", Birthday = new DateTime(2005, 4, 3) };
Console.WriteLine("name:{0},age:{1}",lulu .Name ,DateTime .Now .Year - lulu.Birthday .Year );
匿名类型用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。 类型名由编译器生成,并且不能在源代码级使用。所以在上面的代码里
var lulu= new {} 。由于没有名字,所以我们在代码里是不能使用的。但可以通过var进行读取。这里需要注意匿名类型里的属性都是只读的!
尽管应用程序无法访问匿名类型,但编译器仍会为其提供一个名称。 从公共语言运行时的角度来看,匿名类型与任何其他引用类型没有什么不同,唯一区别在于匿名类型无法强制转换为除 Object 以外的任何类型。
匿名方法
C# 2.0在版本时就已经提供了匿名方法,以前我们使用委托总是需要单独创建方法,现在我们可以通过匿名方法来声明委托。需要注意的是匿名方法中不能使用跳转语句跳转到该匿名方法的外部,也不能跳转到该方法的内部。
public delegate void Print(Cat cat);
......
Print youName = delegate(Cat cat) { Console.WriteLine("Name:{0},Age{1}", cat.Name, cat.Age); };
youName (mili );
先定义一个 Print的 委托类型, 然后在声明youName委托对象这个委托用于打印传入的Cat对象的 信息。使用delegate(type) 来确定匿名方法接受的参数类型,这里需要和定义的委托相同 然后在大括号内定义方法的逻辑。匿名方法的语义比较难以读懂,所以在C# 3.0引入了 Lambda表达式。