• 第七节:语法总结(1)(自动属性、out参数、对象初始化器、var和dynamic等)


    一. 语法糖简介

          语法糖也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

          需要声明的是“语法糖”这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换;而且可以提高开发编码的效率,在性能上也不会带来损失。

          在编译器发展早期,编译器科学家门一直在想方设法的优化编译器生成的代码,这个时候,编译器做的主要是对机器优化,因为那个时候机器的时间非常宝贵,机器运算速度也不快,今天我们有了足够好的机器了(但并不是说我们可以不关注性能的编写程序),而且作为编写软件的人来说,比机器的时间宝贵得多,所以今天的编译器也在向人优化了,从编程语言的发展之路来讲,今天的编程语言比昨天的语言更高级,也更人性化了,我们只要编写更少的代码,更符合人的思维的代码,而只要关注我们值的关注的地方。体力活儿就交给编译器吧。

    二. 常用语法糖

    1. 自动属性

    (1).  传统的方式在类中声明一个属性,需要先声明一个私有变量的字段,然后在配合公有属性,如下面的:userId属性。

    (2). 利用自动属性:不需要字段,声明一个空属性,直接get,set(快捷键:prop),编译时编译器为我们生成存取数据的字段. 如下面的:userName属性。

     1  public class userInfor
     2     {
     3         //私有字段
     4         private string _userId;
     5         //公有属性
     6         public string userId
     7         {
     8             get
     9             {
    10                 return _userId;
    11             }
    12             set
    13             {
    14                 _userId = value;
    15             }
    16         }
    17 
    18         public string useName { get; set; }
    19 
    20 
    21         /// <summary>
    22         /// 为了后面的反射调用
    23         /// </summary>
    24         public void Test()
    25         {
    26             Console.WriteLine("我是一个方法");
    27         }
    28 
    29     }

    2. var和dynamic

    (1). var类型:声明变量的时候可以不指定类型,由编译器编译的时候来指定类型。

      ①:必须在定义的时候初始化

      ②:必须是局部变量

      ③:一旦初始化完成,不能再给变量赋与初始值不同类型的值了,但是可以赋相同类型的不同值.

      ④:var在效率是和使用强类型方式定义变量是一样的

    (2). dynamic类型:编译期间不做任何检查,运行期间才确定类型。

      ①:定义的时候可以不必初始化

      ②:可以是全局变量,也可以是局部变量

       dynamic在反射中的应用:通过反射拿到类后,赋值给dynamic类型,该类型的对象可以直接点来调用方法

       缺点:dynamic在运行的时候才进行检测,导致编译的时候即使有错误也不会被发现; 不能用dynamic类型给确定类型的变量进行赋值

     1  public class CompareTwo
     2     {
     3         //2. 可使用的范围
     4         // var b1 = 1;        //报错,var必须定义在方法呃逆
     5         // dynamic b2 = 2;    //正常
     6         public static void Show()
     7         {
     8             {
     9                 //1. 初始化比较
    10                 //var a1;         //报错,定义的时候必须初始化
    11                 //dynamic a2;     //正常
    12             }
    13             {
    14                 //3. 赋值问题
    15                 var c1 = 2;
    16                 //c1 = "2";   //报错,初始化完成不能赋值不同类型的变量
    17                 c1 = 3;    //正常,初始化完成可以赋值相同类型的变量的不同值
    18 
    19                 dynamic d1 = 2;
    20                 d1 = "2";      //正常,运行时检查进行类型指定,所以在编译的时候不会报错
    21                 d1 = 3;       //正常
    22 
    23 
    24                 var userInfor = new userInfor();
    25                 userInfor.useName = "1";
    26                 userInfor.userId = "2";
    27                 // userInfor.fk123();    //报错,编译不通过
    28 
    29                 dynamic userInfor2 = new userInfor();
    30                 userInfor2.userId = "1";
    31                 userInfor2.useName = "ypf";
    32                 //调用不存在的方法  (因为编译的时候根本不检查,所以不会报错,运行的时候报错)
    33                 //userInfor2.fk123();    //编译期间不报错,运行的时候报错
    34 
    35             }
    36             {
    37                 //4. dynamic在反射中的应用
    38                 //4.1 常规反射调用方法
    39                 Type type1 = typeof(userInfor);
    40                 object oStudent = Activator.CreateInstance(type1);
    41                 MethodInfo method = type1.GetMethod("Test");
    42                 method.Invoke(oStudent,null);
    43 
    44                 //4.2 利用dynamic简化调用
    45                 //定义和编译的时候可以是任何类型,运行的时候进行转换
    46                 dynamic oStudent2 = Activator.CreateInstance(type1);
    47                 oStudent2.Test();
    48 
    49             }
    50         }
    51     }

    3. 可选参数

    给方法的参数可以指定默认值,如果在调用该方法的时候,不传入该参数,则走默认值,传入的话,则覆盖默认参数.

    (1).  有默认值的参数必须定义在没有默认值的参数之后

    (2).  默认参数必须是常量,不能是变量

    (3).  ref和out参数不能指定默认值

    1   public class OptionalParas
    2     {
    3         public static void Test(string useName,string userPwd,int userAge=16,string userSex="")
    4         {
    5             Console.WriteLine("userName:{0},userPwd:{1},userAge:{2},userSex:{3}", useName, userPwd, userAge, userSex);
    6         }
    7     }
    1        //3.可选参数
    2             Console.WriteLine("----------------------3.可选参数-------------------------");
    3             OptionalParas.Test("ypf1", "123456");
    4             OptionalParas.Test("ypf2", "654321", 56, "");

    4. 对象(集合)初始化器

     1  public class ObjectInitilize
     2     {
     3         public static void Test()
     4         {
     5            
     6                 //一.对象初始化
     7                 //1. 传统初始化对象的方式
     8                 userInfor uInfor1 = new userInfor();
     9                 uInfor1.userId = "1";
    10                 uInfor1.useName = "ypf1";
    11 
    12                 //2.对象初始化器
    13                 userInfor uInfor2 = new userInfor()
    14                 {
    15                     userId="2",
    16                     useName="ypf2"
    17                 };
    18                 userInfor uInfor3 = new userInfor()
    19                 {
    20                     userId = "3",
    21                     useName = "ypf3"
    22                 };
    23             
    24                 //二. 集合初始化
    25                 //1. 传统方式
    26                 List<userInfor> uList = new List<userInfor>();
    27                 uList.Add(uInfor1);
    28                 uList.Add(uInfor2);
    29 
    30                 //2. 集合初始化器
    31                 List<userInfor> uList2 = new List<userInfor>(){
    32                     uInfor1,
    33                     uInfor2,
    34                     new userInfor(){
    35                         userId="4",
    36                         useName="ypf4"
    37                     }
    38                 };
    39                 
    40         }
    41     }

    5. ref和out

    二者共同的使用场景,将ref或out参数传入方法中,执行完方法后,可以直接使用ref或out参数值。

      (1). ref必须在使用前赋值,即传入方法前进行定义并赋值

      (2). out必须在方法中赋值然后使用,在调用方法前声明两个未实例化的变量,用来传入和接收使用

    举例:有两个int类型的值num1和num2,分别使用ref和out传入对应的方法中,进行值交换。

     1  public class CompareRO
     2     {
     3         /// <summary>
     4         /// ref的使用
     5         /// </summary>
     6         public static void TestRef()
     7         {
     8             int num1 = 5;
     9             int num2 = 10;
    10             Func1(ref num1, ref num2);
    11             Console.WriteLine("num1的值为:{0},num2的值为:{1}", num1, num2);
    12         }
    13 
    14         public static void TestOut()
    15         {
    16             int num1;
    17             int num2;
    18             Func2(out num1, out num2);
    19             Console.WriteLine("num1的值为:{0},num2的值为:{1}", num1, num2);
    20         }
    21 
    22         #region ref版参数值交换
    23         public static void Func1(ref int n1, ref int n2)
    24         {
    25             int a = n1;
    26             n1 = n2;
    27             n2 = a;
    28         }
    29         #endregion
    30 
    31         #region out版参数值交换
    32         public static void Func2(out int n1,out int n2)
    33         {
    34             n1 = 5;
    35             n2 = 10;
    36             int a = n1;
    37             n1 = n2;
    38             n2 = a;
    39         }
    40         #endregion
    41 
    42     }

    6. 匿名类/匿名方法

       详见:.Net进阶系列(3)-匿名类、匿名方法、扩展方法

    7. 扩展方法

       详见:.Net进阶系列(3)-匿名类、匿名方法、扩展方法

  • 相关阅读:
    python入学代码
    python安装和pycharm安装与笔记
    python预习day1
    python-tyoira基本
    Typora基础
    学习一下saltstack 服务器批量管理
    消息队列与kafka
    消息队列rabbitmq
    redis数据库在linux上的学习
    蓝绿部署、滚动发布、灰度发布的介绍以及最佳实践
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7596031.html
Copyright © 2020-2023  润新知