如果已经熟悉了 C# 1.0 和 C# 2.0 的核心特性,那么利用这些特性,可以实现任何想要实现的应用程序了。但是我们会常常抱怨;我的代码就不能再简洁点吗?微软正式听到这样的声音,才推出 C# 3.0 中的所有特性 C# 3.0 可谓颠覆了我们的代码编写风格,尤其是 Lambda 表达式和 Linq 这两个特性,相信你在习惯后,定会爱上 C# 3.0
自动实现的属性
我们看看 C# 3.0 中对属性语法的改进。在 C# 3.0 之前,定义属性一般会像下面这样去编写代码:
代码语言:javascript复制class Person
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
}
}
}
C# 3.0 之后,对于不需要额外验证的属性(需要额外验证的属性还是必须采用之前的方式来定义),你可以使用自动实现的特性来对属性的定义进行简化,此时不再需要额外定义一个私有的字段了
代码语言:javascript复制class Person
{
public string Name {get; set; }
}
从改写后的代码可以看出,用自动实现的属性来定义属性,确实使代码的定义变得更简洁,它极大地减少了程序员需要敲入的代码量。之所以可以这样定义,主要是因为编译器在编译时会帮我们创建一个私有字段
隐式类型
C# 是强类型语言,在定义一个变量时,需要声明变量的类型。然而类型长度如果过长,就可能会影响代码的可读性。C# 3.0 引入隐式类型,即可以使用关键字 var 来声明变量或者数组,var 关键字告诉编译器去根据变量的值来推断其类型
隐式类型的局部变量
下面来看 var 关键字如何声明局部变量,具体演示代码如下:
代码语言:javascript复制class Program
{
static void Main(string[] args)
{
var stringVariable = "learning hard";
}
}
为什么说用 var 定义的变量对于编译器来说还是显示类型呢?因为在 Visual Studio 中,当你将鼠标放在 var 部分时,可以看到编译器为变量推断类型。并且变量仍然是静态类型,只是你在代码没写出来而已,这个工作交给了编译器,它会根据变量的值去推断类型
使用隐式类型时有一些限制,包括以下几点:
- 被声明的变量时一个局部类型,不能位字段(包括静态字段和实例字段)
- 变量在声明时必须被初始化,因为编译器要根据变量的赋值来推断类型,如果未被初始化,编译器也无法完成推断了。C# 是静态语言,变量类型位置就会出现编译时错误
- 变量不能初始化为 null,因为 null 可以隐式地转换为任何引用类型或可空类型,编译器将不能推断出该变量到底为什么类型
- 不能用 var 来声明方法中的参数
隐式类型数组
使用 var 关键字不仅可以创建隐式类型局部变量,还可以创建数组,例如下面这段代码
代码语言:javascript复制class Program
{
static void Main(string[] args)
{
var arr = new[] { 1, 2, 3 };
var arr1 = new[] { "1", "2", "3" };
}
}
使用隐式类型数组时,编译器也必须要能推断出数组的类型
对象集合初始化器
在 C# 3.0 之前定义类,你往往需要定义多个构造函数来完成不同情况下的初始化。C# 3.0 提供了对象初始化器,它减少了我们在勒中定义的构造函数代码,从而使代码更加简洁。
在没有对象初始化器时,我们会像下面的代码那样去定义类:
代码语言:javascript复制class Program
{
static void Main(string[] args)
{
var p = new Person("Carl", 20);
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person() : this("")
{
}
public Person(string name) : this(name, 0)
{
}
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
}
在 C# 3.0 引入对象初始化器之后,你就不需要定义多个构造函数了,上面代码可以简化为一下的形式:
代码语言:javascript复制class Program
{
static void Main(string[] args)
{
var p1 = new Person() { Name = "Carl" };
var p2 = new Person() { Name = "Carl", Age = 20 };
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
}
从以上代码可知,使用对象初始化器可使对象的初始化代码变得更加简洁
再说说集合初始化器,用来完成对集合中某一元素的初始化。在集合初始化器提出之前,你可能用下面的方式来初始化集合对象:
代码语言:javascript复制static void Main(string[] args)
{
var list = new List<string>();
list.Add("Carl");
list.Add("Karl");
}
有了集合初始化器特性后,你可以用更简洁的代码完成初始化,具体的实现方式如下:
代码语言:javascript复制static void Main(string[] args)
{
var list = new List<string>() { "Carl", "Karl" };
}
编译器在处理集合初始化时,就是调用了 List 的 Add 方法,将对象一个个地添加到了集合对象中
匿名对象
匿名类型,顾名思义就是没有指明类型的类型,通过隐式类型和对象初始化器两种特性创建了一个类型未知的对象,使我们在不定义类型的情况下实现对象的创建,从而减少了类定义过长的代码,减少了开发人员的工作量。下面看匿名类型的使用方法:
代码语言:javascript复制class Program
{
static void Main(string[] args)
{
var p = new { Name = "Carl", Age = 20 };
Console.WriteLine(p.Name);
}
}
总结
熟练掌握自动属性、隐式类型、对象集合初始化器和匿名类型,我们可以让编译器帮助我们创建繁复的代码,大大减少了我们实际开发的工作量。所以说,C# 3.0 的编译器是智能编译器