回顾 .NET 3.0/3.5特性(1)
2012-05-20 16:16 木木子 阅读(229) 评论(0) 编辑 收藏 举报Object Initializers 对象初始化器
之前,经常这样初始化一个对象:
User user = new User();
user.Age = 23;
user.Name = "sanity";
有了3.0后,就这样初始化对象了:
User user = new User { Age = 23, Name = "Sanity" };
对象初始化器把代码变得简洁和优美了。
本质分析——对象初始化器,反编译结果:
User <>g__initLocal0 = new User {
Age = 0x17,
Name = "Sanity"
};
User user = <>g__initLocal0;
从反编译结果看出来,编译器对代码初始化器做了处理:声明一个User的临时变量 <>g__initLocal0,对这个临时变量赋值,然后将初始化好的临时变量赋给user变量。
Collection Initializers 集合初始化器
2.0中,我们初始化一个list,通过Add方法来加入值:
List<User> users = new List<User>();
users.Add(new User { Age = 23, Name = "sanity" });
users.Add(new User { Age = 24, Name = "Lin" });
3.0中的集合初始化器这样来构建一个list:
List<User> users = new List<User>
{
new User { Age = 23, Name = "sanity" },
new User { Age = 24, Name = "Lin" }
};
同样的反编译看下本质代码:
List<User> <>g__initLocal0 = new List<User>();
User <>g__initLocal1 = new User {
Age = 0x17,
Name = "sanity"
};
<>g__initLocal0.Add(<>g__initLocal1);
User <>g__initLocal2 = new User {
Age = 0x18,
Name = "Lin"
};
<>g__initLocal0.Add(<>g__initLocal2);
List<User> users = <>g__initLocal0;
同样的,从IL看出,编译器也为集合初始化器生成了临时变量,本质还是跟之前的相同。
Automatic Properties 自动属性
2.0方式:
public class User
{
// Fields
private int age;
private string name;
// Methods
public User();
// Properties
public int Age { get; set; }
public string Name { get; }
}
3.0:
public class User
{
public int Age { get; private set; }
public string Name { get; set; }
}
对于自动属性还有些规则:
1. 有附加逻辑的字段无法用自动属性实现,还是得需要传统的属性定义方式。
2. 必须同时实现get和set,对于只读或者只写属性,可为访问器添加private修饰符。
3. 还需要注意abstract property的自动属性实现。
Implicitly Typed Local Variables 隐式类型变量
Implicitly Typed Array 隐式类型数组
var i = 23;
var str = "Hello, Implicitly Type.";
var user = new User { Age = 23, Name = "Sanity" };
var users = new List<User>
{
new User { Age = 23, Name = "sanity" },
new User { Age = 24, Name = "Lin" }
};
看上述代码中,使用了javascript中到处可见的var声明变量,3.0也实现了var声明变量,这样意味着.NET变成了弱类型语言吗?Nope!
本质分析:
User <>g__initLocal0 = new User {
Age = 0x17,
Name = "Sanity"
};
User user = <>g__initLocal0;
List<User> <>g__initLocal1 = new List<User>();
User <>g__initLocal2 = new User {
Age = 0x17,
Name = "sanity"
};
<>g__initLocal1.Add(<>g__initLocal2);
User <>g__initLocal3 = new User {
Age = 0x18,
Name = "Lin"
};
<>g__initLocal1.Add(<>g__initLocal3);
List<User> users = <>g__initLocal1;
在IL中看出,其实编译器能够反推出变量本身的类型,我们只是通过var关键字将变量类型的声明托付给了编译器来完成。
对于var的几点规则:
1. 在.NET中,我们可以用object来声明任何类型变量,但这种声明方式存在着类型转换操作,而且如果变量为值类型的话,还会引起装箱,影响性能了。而var的实现,不存在这些现象;
2. 用var声明的变量必须进行初始化,而且不能为null,也不能类型不确定的表达式,否则编译器不能判断是什么类型;
3. 隐式类型还是强类型,是将类型声明交给编译器来完成了。
Anonymous Type
在隐式类型和对象初始化的帮助下,可以实现匿名类型了。
之前的User Class这样定义和使用:
public class User
{
public int Age { get; set; }
public string Name { get; set; }
}
var user = new User { Age = 23, Name = "Sanity" };
匿名类型让这一切变得更加简单:
var user = new { Age = 23, Name = "Sanity" };
匿名类型规则是:对象初始化器中的参数名称、类型和顺序都一致时,这些匿名类型的对象才是同一个类型。
Extension Methods扩展方法
扩展方法实现了在保持原有类型不做任何改变的情况下,对其进行扩展。实例:
static class MyExtensions
{
public static void ShowInfo(this User user)
{
Console.WriteLine("Name: {0}\nAge: {1}", user.Name, user.Age);
}
public static void TellType(this User user)
{
Console.WriteLine("I am a user:");
user.ShowInfo();
}
}
调用实例方法一样来调用扩展方法:
static void Main(string[] args)
{
var user = new User { Age = 23, Name = "Sanity" };
user.ShowInfo();
user.TellType();
Console.ReadKey();
}
扩展方法规则:
1. 实例方法优先于扩展方法,命名空间内的扩展方法优先于命名空间外的。
2. 扩展方法可以继承;
3. 只支持对方法的扩展,不支持属性、事件。
4. 扩展方法是LINQ实现的基本条件;
5. 必须以this关键字标识扩展方法的第一个参数;
6. 扩展方法必须被实现为静态方法,被定义在非泛型静态类中。
参考资料:
1. Clr Via C#
2. C# in depth
3. 你必须知道的.NET