zoukankan      html  css  js  c++  java
  • 用智能的编译器来防错

    自动实现的属性

    编写由字段直接支持的简单属性,不再显得臃肿不堪
    C#2允许为取值方法指定不同的访问权限
    #region 8-1统计创建了多少个实例的Person类
    public class Person
    {
    public string Name { get; private set; }//声明有公有取值方法的属性
    public int Age { get; private set; }
     
    private static int InstanceCounter { get; set; }//声明私有的静态属性和锁
    private static readonly object counterLock = new object();
     
    public int InstanceCounterPerson(string name, int age)
    {
    Name = name;
    Age = age;
     
    lock (counterLock)//访问静态属性时使用锁。应避免锁定 public 类型,否则实例将超出代码的控制范围
    {
    InstanceCounter++;
    }
    return InstanceCounter;
    }
    }
    #endregion
    #region 写一个有单个整数属性的结构
    public struct Foo
    {
    public int Value { get; private set; }//所有字段在被设置之前,不能使用这些属性
     
    public Foo(int value)
    : this()//显示的调用无参构造函数this(),编译器才知道所有字段都被明确的赋值了
    {
    this.Value = value;//调用无参构造函数,改字段被设为默认值
    }
    }
    #endregion
    隐式类型的局部变量
    根据初始化值推断变量的类型,从而简化局部变量的声明
    用var声明局部变量
    使用隐式类型,唯一要做的就是将普通局部变量声明类型名称替换为var
    编译器工作:获取初始化表达式在编译时的类型,并使变量也具有那种类型
    变量是静态的类型,只是由编译器推断
    隐式类型的限制
    • 被声明的变量是一个局部变量,而不是一个静态字段和实例字段
    • 变量在声明的同时被初始化
    • 初始化表达式不是方法组也不是匿名函数
    • 初始化表达式不是null
    • 语句中只声明了一个变量
    • 你希望变量拥有的类型是初始化编译时的类型
    • 初始化表达式不包含正在声明的变量
    不能这样写:var starter=delegate(){Console.WretrLine()}
    可以这样写:var starter=(ThreadStart)delegate(){Console.WretrLine()}
    同样的也适用于null
    var argss = Environment.GetCommandLineArgs();//用方法的调用结果来初始化一个变量
    隐式类型的建议
    • 如果代码让人一眼就能看出变量类型很重要,就使用显示类型
    • 如果变量直接用一个构造函数初始化,而且类型名称很长,就考虑使用隐式类型
    • 如果变量的确切类型不重要,而且它的本质在当前上下文已经很清楚,就用隐式类型,从而不去强调代码具体是如何达到目标的,而是关注它想要达到什么目标
    • 看哪个顺眼
    对象和集合的初始化程序
    用一个表达式就能轻松创建初始化对象
    对象初始化程序:初始化列表指定了在对象创建好后,如何对其进行初始化
    #region 8-2一个相当简单的Person类
    public class Person
    {
    public int Age { get; set; }
    public string Name { get; set; }
     
    List<Person> friends = new List<Person>();//对象创建时,以留空的方式创建,而不是保留空引用
    public List<Person> Friends { get { return friends; } }
     
    Location home = new Location();//对象创建时,以留空的方式创建,而不是保留空引用
    public Location Home { get { return home; } }
     
    public Person() { }
     
    public Person(string name)
    {
    Name = name;
    }
    }
     
    public class Location
    {
    public string Country { get; set; }
    public string Town { get; set; }
    }
    #endregion
    设置简单属性
    对象初始化程序最常用于设置属性
    Person tom1 = new Person();
    tom1.Name = "Tom";
    tom1.Age = 9;
     
    Person tom2 = new Person { Name = "Tom", Age = 9 };//tom1在IL中
     
    Person tom3 = new Person("Tom");
    tom3.Age = 9;
     
    Person person3 = new Person("Tom") { Age = 9 };//tom3在IL中
     
    Person[] family = new Person[]
    {
    new Person{Name="Holly1",Age=36},
    new Person{Name="Holly2",Age=36},
    new Person{Name="Holly3",Age=36},
    new Person{Name="Holly4",Age=36}
    };
    为嵌入对象设置属性
    Person tom4 = new Person("Tom");//设置一个嵌入对象属性
    tom4.Age = 9;
    tom4.Home.Country = "CS";
    tom4.Home.Town = "WC";
     
    Person tom5 = new Person("Tom") { Age = 9, Home = { Country = "CS", Town = "WC" } };//设置一个嵌入对象属性
     
    Person tom6 = new Person("Tom");//设置一个嵌入对象属性
    tom6.Age = 9;
    tom6.Home.Country = "CS";
    tom6.Home.Town = "WC";
    集合初始化程序
    #region 集合初始化程序
    var names = new List<string>
    {
    "Holly","jon","Tom","Robin","William"
    };
     
    List<string> names1 = new List<string>();//动态添加,IL中无该处代码
    names1.Add("Holly1");
    names1.Add("jon1");
    names1.Add("Tom1");
    names1.Add("Robin1");
    names1.Add("William1");
     
    Dictionary<string, int> nameAgeMap = new Dictionary<string, int>//任何实现IEnumerable的类型,只要它为初始化列表中出现的每个元素提供了一个公有Add方法,就可以使用这个特性
    {
    {"Holly",36},//Add方法被调用3次,如果Add有多个重载版本,那么初始化列表每个不用元素都可以调用不通的重载版本
    {"Jon",36},
    {"Tom",9}
    };
    #endregion
    在其他对象初始化程序中填充集合
    与对象初始化程序组合使用
    #region 8-3使用对象1和集合初始化程序来构建一个“富对象”
    Person tom = new Person
    {
    Name = "Tom",
    Age = 9,
    Home = { Town = "WC", Country = "CS" },//初始化嵌入对象
    Friends = //对象初始化程序来初始化集合
    {
    new Person{Name="Alberto"},
    new Person("MAx"),
    new Person{Name="Zak",Age=9},
    new Person("Ben"),
    new Person("Alice")
    {
    Age=9,
    Home={Town="C",Country="S"}
    }
    }
    };
    #endregion
    初始化特性的应用
    常量集合
    设置单元测试
    builder模式
    隐式类型数组
    MyMethod(new[] {"HE","EH"});
    首先构造一个集合,其中包括大括号内所有的表达式的编译时的类型,在这个类型集合中,如果其他所有类型都能隐式转换为其中一种类型,改类型即为数组类型
    匿名类型
     
    #region 8-4创建具有Name和Age属性的匿名类型对象
    var tom = new { Name = "Tom", Age = 9 };//匿名对象初始化程序
    Console.WriteLine("{0},{1}", tom.Name, tom.Age);//属性具有和初始化程序中的表达式一样的类型,值在创建匿名对象初始化程序中指定
    #endregion
    #region 8-5用匿名类型填充数组,并计算总年龄
    var family = new[]//使用隐式类型的数组初始化程序
    {
    new{Name="Holly",Age=36},//使用匿名对象初始化程序
    new{Name="Jon",Age=32}//如果生成不同的类型,编译器无法判断声明数组的类型
    };
     
    int totalAge = 0;
    foreach (var person in family)//对每个人使用隐式类型
    {
    totalAge += person.Age;
    }
    Console.WriteLine("Total age:{0}", totalAge);
    #endregion
    投影初始化程序
    #region 8-6从Person对象转换成一个名字和一个成年标志
    List<Person> family = new List<Person>
    {
    new Person{Name="Holly",Age=36},
    new Person{Name="Jon",Age=23},
    new Person{Name="Jon",Age=23}
    };
    var converted = family.ConvertAll(delegate(Person person)
    { return new { person.Name, IsAdult = (person.Age >= 18) }; });//投影初始化程序:如果不指定属性名称,而只指定用于求值的表达式,它就会使用表达式最后一部分作为名称————前提是它只能是一个简单的字段和属性
    foreach (var person in converted)
    {
    Console.WriteLine("{0} is an adult?{1}", person.Name, person.IsAdult);
    }
    #endregion

     

  • 相关阅读:
    hdu 4893 Wow! Such Sequence!(线段树)
    Leetcode Best Time to Buy and Sell Stock II
    Debian GNU Linux服务列表的获取、服务的关闭/开启、服务在启动时是否自己主动执行的生效/失效
    R语言中数据结构
    C#编写Windows服务程序 (服务端),client使用 消息队列 实现淘宝 订单全链路效果
    deep learning实践经验总结
    Java编程思想第四版 *第五章 个人练习
    CEPH OBJECTSTORE API介绍
    leetcode(58)-Range Sum Query
    Android百日程序:GridView实现相冊效果
  • 原文地址:https://www.cnblogs.com/Tan-sir/p/5169216.html
Copyright © 2011-2022 走看看