C# 3.0 新特性 学习(一):隐式类型化本地变量、自动属性、初始化器(对象初始化器和集合初始化器)

时间:2022-09-03 19:11:02
  1. 隐式类型化本地变量
    注:
    当一个本地变量声明标示为var作为类型并且没有var类型名称在范围内,那么这个声明被视作隐式类型化的本地变量声明。
    什么意思呢?也就是说当我们声明本地变量时。使用var n=100; 这种声明方式,而 var又不是我们自己定义的类型,那这种用var 声明的变量就叫隐式类型化变量。而且只支持本地化变量的隐式类型的声明。有人可能会问:啥叫本地变量啊?其实本地变量就是局部变量,在方法中声明的变量;与之对应的是全局变量在类中声明的变量。也就是说var 这种声明方式只能在方法内部使用,全局变量是不支持隐式类型化声明的。例如:
    class Program
    {
           var a =  5; // 这里 编译通不过,var 声明只允许在 本地变量(局部变量)声明时使用。
           static  void Main( string[] args)
          {
                var n =  100;
               // var v = new var();
          }
    }
    在一个隐式类型化的本地变量声明中,本地变量的类型是由使用的表达式初始化变量来推断的。
    上面这句话什么意思呢?看下面:
    var i=5; 在VS将鼠标放在var关键字上就会显示 var 其实是一个int32类型;也就是说 i 这个变量的类型是由 它右边的初始化值的类型来决定的。
    var s="hello";  因为它的值是一个字符串,所以这里的 s 的类型是string。隐式类型化本地变量 在编译的时候,编译器会自动根据它右边的值,来确定定它的类型。
    var的其它使用: 
     1  namespace Demo
     2 {
     3      class Program
     4     {
     5          // var a = 5;
     6           static  void Main( string[] args)
     7         {
     8              // 以前是我们是这样写的
     9               int i =  5;
    10              string s =  " Hello ";
    11              double d =  1.0;
    12              int[] numbers =  new  int[] {  123 };
    13             Dictionary< int, Student> orders =  new Dictionary< int, Student>();
    14             Student student =  new Student();
    15              // 有了 隐式类型化声明侯 我们可以这样写
    16               var n =  5;
    17              var str =  " Hello ";
    18              var db =  1.0;
    19              var num =  new  int[] {  123 };
    20              var sdt_dict =  new Dictionary< int, Student>();
    21              var sdt =  new Student();
    22         }
    23     }
    24      public  class Student { }
    25      // public class var
    26       // {
    27       // }
    28  }
    隐式类型化的声明还应注意一下几点:
    • 声明者必须包含一个构造者。
    • 这个构造器必须是一个表达式。这个构造器不能够是一个对象或者构造器集合的自身,但是它可以是一个新的包含一个对象或者构造器集合的表达式。 
    • 在编译时刻构造器表达式的类型不能为null类型。

      Sample :  var x = null //编译不通过 错误 无法将“<null>”赋予隐式类型的局部变量

    • 如果本地变量声明包含多种构造器,那么构造器必须都具有相同的编译时类型

      Sample :var s="hello"; //构造器为一个具体的string类型的值。所以更改构造器时,构造器也应该返回一个string类型的值,或者是一个具体的string类型值。

      s=GetStr();  //GetStr 返回一个字符串.   s=5; //这样编译不通过。 原因就是 "多种构造器,那么构造器必须都具有相同的编译时类型“

  2. 自动属性
    自动属性允许你避免手工声明一个私有成员变量以及编写get/set逻辑,取而代之的是,编译器会自动为你生成一个私有变量和默认的get/set 操作。

    怎么实现?如下:

     1   public  class Student
     2  {
     3          // 以前我们这样写。快捷方式:将光标停在要封装属性的字段上,按 Ctrl + r + e;
     4           private  string name;
     5 
     6          public  string Name
     7         {
     8              get {  return name; }
     9              set { name = value; }
    10         }
    11          // 现在有了自动属性,我们可以如下写。编译器会自动生成一个get;set;的实现
    12           public  int Age {  getset; }
    13         
    14          public DateTime BirthDay {  getprivate  set; }
    15  }

     

    要注意的是:

    1.自动属性适用于 当属性访问器中不需要其他逻辑时。什么意思呢?也就是说我们的get或者set时,不要做处理;有些属性可能在赋值或者取值的时候我们自己可以在get或者set访问器做一些处理。但是大多数情况下是不要做处理的。当不需要做处理时,你就可以用C#3.0的新特性 这种自动属性来简化我们的编码。如果要对get 或者set访问器写自己的逻辑代码的话,那就还是使用以前的那种方式。

    2.自动实现的属性必须同时声明get 和set 访问器。若要创建readonly 自动实现属性,请给予它private set 访问器。

     Sample : public int Age{get;} //编译不通过 。 必须同时声明get 和set 访问器
                  public int Age{ get; private set;} //定义了一个自读属性。set访问器是私有的。

  3. 对象初始化器和集合初始化器
    初始化器允许我们在实例化对象或集合时同时指定对象公有属性的值或指定集合的元素。
    Sample:
     1  namespace Demo
     2 {
     3      class Program
     4     {
     5          static  void Main( string[] args)
     6         {
     7              // 以前我们可能这么写
     8               // 对象
     9              Person p1 =  new Person();
    10             p1.Name =  " Joey ";
    11             p1.Age =  25;
    12              // 集合
    13              List<Person> ps1 =  new List<Person>();
    14             Person joey =  new Person();
    15             joey.Name =  " joey ";
    16             joey.Age =  25;
    17             Person zhangSan =  new Person();
    18             zhangSan.Name =  " ZhangSan ";
    19             zhangSan.Age =  18;
    20              // 然后加入集合
    21              ps1.Add(joey);
    22             ps1.Add(zhangSan);
    23              // 数组
    24               int[] a1 =  new  int[ 3];
    25             a1[ 0] =  1;
    26             a1[ 1] =  2;
    27             a1[ 2] =  3;
    28 
    29              // 有了初始化器后 我们可以这么写
    30               // 对象
    31               var p2 =  new Person { Name =  " Joey ", Age =  25 };
    32 
    33              // 集合
    34               var ps2 =  new List<Person> { 
    35                  new Person{ Name= " Joey ", Age= 25 },
    36                  new Person{Name= " ZhangSan ", Age= 18 }
    37             };
    38              // 数组
    39               var a2 =  new  int[] {  123 };
    40         }
    41     }
    42 
    43      public  class Person
    44     {
    45          public  int ID {  getprivate  set; }
    46 
    47          public  string Name {  getset; }
    48          public  int Age {  getset; }
    49 
    50     }
    51 }
    是不是感觉 简化了很多呢?这就是初始化器给我们带来的便捷。不过初始化器的使用也有一些约束:
    • 可以和构造函数一起使用
      Sample:
         1   namespace  Demo
     2 {
     3      class Program
     4     {
     5          static  void Main( string[] args)
     6         {
     7              // 与构造函数一起使用 ,并且构造函数会先于构造器执行。
     8               var p3 =  new Person( 1) { Name =  " joey ", Age =  25 };
     9         }
    10     }
    11 
    12      public  class Person
    13     {
    14          public Person( int id)
    15         {
    16              this.ID = id;
    17         }
    18          public  int ID {  getprivate  set; }
    19 
    20          public  string Name {  getset; }
    21          public  int Age {  getset; }
    22 
    23     }
    24 }
    • 允许部分赋值

       拿上面的例子来说:就是允许这样实例化:var p=new Person(1){ Name=”joey" }; 而不给Age属性赋值。 

    • 允许给internal成员赋值
    • 构造函数比对象初始化器先执行