自动实现属性
C#提供的set/get可以让我们很方便的使用属性,但是某些情况下书写还是稍微麻烦了点,如下:
1 public class Test 2 { 3 private string _name; 4 5 public string name 6 { 7 set { _name = value; } 8 get { return _name; } 9 } 10 }
这种情况我们可以如下进行简写:
1 public class Test 2 { 3 public string name { set; get; } 4 }
当然,实际上我们在编译的时候,编译器会自动帮我们生成类似于没有简化的代码的样子。
隐式类型
我们如果在声明变量时想偷偷懒的话,可以使用隐式类型关键字var,如下:
string str1 = "hello"; var str2 = "world"; var str3 = str1; var str4 = str2;
上面的4个变量都是string类型的,而使用var定义的话,则把类型交给编译器,编译器会根据我们赋予的值确定变量的类型,最后编译时编译器会编译为如下的代码:
string str1 = "hello"; string str2 = "world"; string str3 = str1; string str4 = str2;
我们看看隐式类型需要注意的地方:
- 声明的变量必须是局部变量,不能为静态字段或实例字段;
- 变量声明时必须进行初始化;
- 变量不能初始化为方法组或匿名函数;
- 变量不能初始化为null;
- 不能用var来声明方法中的参数;
- 不能使用没有赋值的变量赋值给var,如下是错误的:
string str1; var str2 = str1;
隐式类型数组
隐式类型同样可以用在数组上:
var a1 = new[] { 0, 1, 2 }; var a2 = new[] { "a", "b", "c" };
初始化器
初始化器可以在实例化一个对象时直接设置其内部public属性的值,可以避免手动编写大量的构造函数,如下:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 //普通初始化 10 Test t1 = new Test(); 11 Console.WriteLine(t1); 12 Test t2 = new Test(10); 13 Console.WriteLine(t2); 14 15 //使用初始化器初始化 16 Test t3 = new Test { a = 1, b = 2.5f }; 17 Console.WriteLine(t3); 18 Test t4 = new Test(100) { b = 1.111f }; 19 Console.WriteLine(t4); 20 21 Console.Read(); 22 } 23 } 24 25 public class Test 26 { 27 public int a; 28 29 public float b; 30 31 public Test() 32 { 33 } 34 35 public Test(int a) 36 { 37 this.a = a; 38 } 39 40 public override string ToString() 41 { 42 return "a: " + a + ", b: " + b; 43 } 44 } 45 }
结果如下:
1 a: 0, b: 0 2 a: 10, b: 0 3 a: 1, b: 2.5 4 a: 100, b: 1.111
集合的初始化器
当我们创建集合的时候,就可以使用初始化器向集合中添加已经设定好值的对象了,方便快捷:
1 using System; 2 using System.Collections.Generic; 3 4 namespace Study 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 //列表 11 List<Test> list = new List<Test> 12 { 13 new Test(), 14 new Test{a = 1, b = 0.1f}, 15 new Test(100){b = 200.5f}, 16 null, 17 }; 18 19 //哈希表 20 Dictionary<int, Test> map = new Dictionary<int, Test> 21 { 22 {1001, new Test()}, 23 {1002, new Test{a = 1, b = 0.1f}}, 24 {1003, new Test(100){b = 200.5f}}, 25 {1004, null}, 26 }; 27 28 Console.Read(); 29 } 30 } 31 32 public class Test 33 { 34 public int a; 35 36 public float b; 37 38 public Test() 39 { 40 } 41 42 public Test(int a) 43 { 44 this.a = a; 45 } 46 47 public override string ToString() 48 { 49 return "a: " + a + ", b: " + b; 50 } 51 } 52 }
匿名类
另外初始化器还可以生成匿名类,但是需要注意的是匿名类中的属性是只读的:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 var person = new {name = "Alen", age = 30}; 10 //这是不允许的 11 //person.age = 20; 12 Console.WriteLine(person.age); 13 14 Console.Read(); 15 } 16 } 17 }
可选参数
在C#4.0之前我们对方法参数设置默认值时一般使用重载,一般是这么写的:
1 public void Func(int a, int b) 2 { 3 //... 4 } 5 6 public void Func(int a) 7 { 8 Func(a, 10); 9 }
如果使用可选参数则会更加方便:
1 public void Func(int a, int b = 10) 2 { 3 //... 4 }
可选参数需要注意的地方:
- 可选参数必须位于必选参数之后;
- 可选参数的默认值必须是常量,如数字、常量字符串、null、const成员和枚举成员等。
- params修饰的参数数组不能为可选参数;
- ref或out引用传递的参数不能为可选参数;
命名实参
一般配合可选参数使用,我们具体来看一个例子:
1 public static void Func(int a, int b = 10, bool c = true, string d = "center", int e = 20) 2 { 3 //... 4 }
如果只需要设置参数a和e,其它参数均保持默认值,一般的写法如下:
Func(0, 10, true, "center", 30);
试想一下,如果默认参数特别多但是我们只需要设定最后一个参数时,是不是感觉要写死,不用担心,C#引入的命名实参可以帮我们解决这个问题,我们只需要这么编写即可:
//只为可选参数指定命名实参 Func(0, e : 30); //为所有参数指定命名实参 Func(a : 0, e : 30);