C# in depth (第八章 用智能的编译器来防错)

8.1   自动实现的属性

公开可见的静态成员通常应该是线程安全的,编译器在这方面帮不上什么忙,得自己去实现

public class InstanceCountingPerson
    {
        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 InstanceCountingPerson(string name, int age)
        {
            Name = name;
            Age = age;

            lock (counterLock)
            {
                InstanceCounter++;
            }
        }
    }

 作者见过的使用静态自动属性的唯一情况是,取值方法是公共的,赋值方法是私有的,并且赋值方法只能在类型初始化程序中使用。 

(以下代码无法通过编译)

  public struct Foo
    {

        public int Value { get; private set; }

        public Foo(int value)
        {
            this.Value = value;
        }
    }

只有加上this 才可以

 public struct Foo
    {

        public int Value { get; private set; }

        public Foo(int value) :this()
        {
            this.Value = value;
        }
    }

 8.2 隐式类型的局部变量

8.2.1 用var声明局部变量

8.2.2 隐式类型的限制

  • 被声明的变量是一个局部变量,而不是静态字段和实例字段。
  • 变量在声明的同时被初始化;
  • 初始化表达式不是方法组,也不是匿名函数。
  • 初始化表达式不是null
  • 语句中只声明了一个变量。
  • 你希望变量拥有的类型是初始化表达式的编译时类型
  • 初始化表达式不包含正在声明的变量。

8.2.3 隐式类型的优缺点

8.2.4 建议

8.3 简化的初始化

8.3.1定义示例类型

 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; }
    }

8.3.2 设置简单属性

Person tom3 =new Person(){ Name ="Tom", Age=9};
Person tom4 =new Person{ Name ="Tom", Age=9};
Person tom5 =new Person("Tom") {Age=9};

 

C#3.0可以用一个表达式来设置对象的所有属性

Person[] family = new Person[]
{
    new Person{Name ="Holly", Age=36},
    new Person{Name ="Jon", Age=36},
    new Person{Name ="Tom", Age=9},
    new Person{Name ="William", Age=6},
    new Person{Name ="Robin", Age=6}
}

 

8.3.3 为嵌入对象设置属性

Person tom = new Person("Tom")
{
      Age =9;
      Home ={Country ="UK", Town ="Reading"}
}

 

8.3.4 集合初始化程序

1.使用集合初始化程序来创建新集合。

var names = new List<string>{"Holly","Jon","Tom","Robin","Williaam"};

 2.在其他对象初始化程序中填充集合

 class ObjectInitializer
    {
        static void Main()
        {
            Person tom = new Person
            {
                Name = "Tom",
                Age = 9,
                Home = { Town = "Reading", Country = "UK" },
                Friends =
                {
                    new Person { Name = "Alberto" },
                    new Person("Max"),
                    new Person { Name = "Zak", Age = 7 },
                    new Person("Ben"),
                    new Person("Alice")
                    {
                        Age = 9,
                        Home = { Town = "Twyford", Country="UK" }
                    }
                }
            };
        }
    }

8.3.5 初始化特性的应用

8.4 隐式类型的数组

例如,以下语句编译起来没有任何问题

string[] names = {"Holly", "Jon", "Tom", "Robin", "William" };

 但这种写法不适用于参数:

MyMethod(("Holly","Jon","Tom","Robin","William");
这种写法无法通过编译。

需要写成这样:

MyMethod(new[]("Holly","Jon","Tom","Robin","William")));

8.5 匿名类型

 如果分开来看,隐式类型对象和组合初始化程序以及隐士数组类型均有或大或小的用处。然而它们也可以组合起来使用,从而服务于一个更高的目标,也就是本章最后要讲述的一个特性:匿名类型。而匿名类型又服务员一个更高的目标:LINQ

8.5.1 第一次邂逅匿名类型

 class FirstAnonymousType
    {
        static void Main()
        {
            var tom = new { Name = "Tom", Age = 9 };
            var holly = new { Name = "Holly", Age = 37 };
            var jon = new { Name = "Jon", Age = 36 };

            Console.WriteLine("{0} is {1} years old", jon.Name, jon.Age);
        }
    }
 class AnonymousTypeInArray
    {
        static void Main()
        {
            var family = new[]                         
            {
                new { Name = "Holly", Age = 37 },      
                new { Name = "Jon", Age = 36 },        
                new { Name = "Tom", Age = 9 },         
                new { Name = "Robin", Age = 6 },       
                new { Name = "William", Age = 6 }      
            };

            int totalAge = 0;
            foreach (var person in family)
            {
                totalAge += person.Age;
            }
            Console.WriteLine("Total age: {0}", totalAge);
        }
    }

8.5.2 匿名类型的成员

匿名类型包含以下成员:

  • 一个获取所有初始值的构造函数。参数的顺序和它们在匿名对象初始化程序中的顺序一样,名称和类型也一样;
  • 公有的只读属性
  • 属性的私有只读字段
  • 重写的Equals,GetHashCode和ToString。

8.5.3 投影初始化程序

class Projection
    {
        static void Main()
        {
            List<Person> family = new List<Person>                 
            {
                new Person { Name="Holly", Age=37 },
                new Person { Name="Jon", Age=36 },
                new Person { Name="Tom", Age=9 },
                new Person { Name="Robin", Age=6 },
                new Person { Name="William", Age=6 }
            };

            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);
            }
        }
    }

8.5.4 重点何在

                    避免过度的数据积累

                          匿名类型

为一种进行裁减的数据封装   避免手动编写重复的代码

 

posted @ 2015-08-21 18:39  莱茵哈特  阅读(186)  评论(0编辑  收藏  举报