您的位置:首页 > 其它

用智能的编译器来防错

2016-01-29 15:46 295 查看
自动实现的属性

编写由字段直接支持的简单属性,不再显得臃肿不堪

C#2允许为取值方法指定不同的访问权限

#region8-1统计创建了多少个实例的Person类

publicclassPerson

{

publicstringName{get;privateset;}//声明有公有取值方法的属性

publicintAge{get;privateset;}


privatestaticintInstanceCounter{get;set;}//声明私有的静态属性和锁

privatestaticreadonlyobjectcounterLock=newobject();


publicintInstanceCounterPerson(stringname,intage)

{

Name=name;

Age=age;


lock(counterLock)//访问静态属性时使用锁。应避免锁定public类型,否则实例将超出代码的控制范围

{

InstanceCounter++;

}

returnInstanceCounter;

}

}

#endregion


#region写一个有单个整数属性的结构

publicstructFoo

{

publicintValue{get;privateset;}//所有字段在被设置之前,不能使用这些属性


publicFoo(intvalue)

:this()//显示的调用无参构造函数this(),编译器才知道所有字段都被明确的赋值了

{

this.Value=value;//调用无参构造函数,改字段被设为默认值

}

}

#endregion


隐式类型的局部变量

根据初始化值推断变量的类型,从而简化局部变量的声明

用var声明局部变量
使用隐式类型,唯一要做的就是将普通局部变量声明类型名称替换为var
编译器工作:获取初始化表达式在编译时的类型,并使变量也具有那种类型
变量是静态的类型,只是由编译器推断
隐式类型的限制

被声明的变量是一个局部变量,而不是一个静态字段和实例字段

变量在声明的同时被初始化

初始化表达式不是方法组也不是匿名函数

初始化表达式不是null

语句中只声明了一个变量

你希望变量拥有的类型是初始化编译时的类型

初始化表达式不包含正在声明的变量

不能这样写:varstarter=delegate(){Console.WretrLine()}
可以这样写:varstarter=(ThreadStart)delegate(){Console.WretrLine()}
同样的也适用于null

varargss=Environment.GetCommandLineArgs();//用方法的调用结果来初始化一个变量


隐式类型的建议

如果代码让人一眼就能看出变量类型很重要,就使用显示类型

如果变量直接用一个构造函数初始化,而且类型名称很长,就考虑使用隐式类型

如果变量的确切类型不重要,而且它的本质在当前上下文已经很清楚,就用隐式类型,从而不去强调代码具体是如何达到目标的,而是关注它想要达到什么目标

看哪个顺眼

对象和集合的初始化程序

用一个表达式就能轻松创建初始化对象

对象初始化程序:初始化列表指定了在对象创建好后,如何对其进行初始化

#region8-2一个相当简单的Person类

publicclassPerson

{

publicintAge{get;set;}

publicstringName{get;set;}


List<Person>friends=newList<Person>();//对象创建时,以留空的方式创建,而不是保留空引用

publicList<Person>Friends{get{returnfriends;}}


Locationhome=newLocation();//对象创建时,以留空的方式创建,而不是保留空引用

publicLocationHome{get{returnhome;}}


publicPerson(){}


publicPerson(stringname)

{

Name=name;

}

}


publicclassLocation

{

publicstringCountry{get;set;}

publicstringTown{get;set;}

}

#endregion


设置简单属性
对象初始化程序最常用于设置属性

Persontom1=newPerson();

tom1.Name="Tom";

tom1.Age=9;


Persontom2=newPerson{Name="Tom",Age=9};//tom1在IL中


Persontom3=newPerson("Tom");

tom3.Age=9;


Personperson3=newPerson("Tom"){Age=9};//tom3在IL中


Person[]family=newPerson[]

{

newPerson{Name="Holly1",Age=36},

newPerson{Name="Holly2",Age=36},

newPerson{Name="Holly3",Age=36},

newPerson{Name="Holly4",Age=36}

};


为嵌入对象设置属性

Persontom4=newPerson("Tom");//设置一个嵌入对象属性

tom4.Age=9;

tom4.Home.Country="CS";

tom4.Home.Town="WC";


Persontom5=newPerson("Tom"){Age=9,Home={Country="CS",Town="WC"}};//设置一个嵌入对象属性


Persontom6=newPerson("Tom");//设置一个嵌入对象属性

tom6.Age=9;

tom6.Home.Country="CS";

tom6.Home.Town="WC";


集合初始化程序

#region集合初始化程序

varnames=newList<string>

{

"Holly","jon","Tom","Robin","William"

};


List<string>names1=newList<string>();//动态添加,IL中无该处代码

names1.Add("Holly1");

names1.Add("jon1");

names1.Add("Tom1");

names1.Add("Robin1");

names1.Add("William1");


Dictionary<string,int>nameAgeMap=newDictionary<string,int>//任何实现IEnumerable的类型,只要它为初始化列表中出现的每个元素提供了一个公有Add方法,就可以使用这个特性

{

{"Holly",36},//Add方法被调用3次,如果Add有多个重载版本,那么初始化列表每个不用元素都可以调用不通的重载版本

{"Jon",36},

{"Tom",9}

};

#endregion


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

与对象初始化程序组合使用

#region8-3使用对象1和集合初始化程序来构建一个“富对象”

Persontom=newPerson

{

Name="Tom",

Age=9,

Home={Town="WC",Country="CS"},//初始化嵌入对象

Friends=//对象初始化程序来初始化集合

{

newPerson{Name="Alberto"},

newPerson("MAx"),

newPerson{Name="Zak",Age=9},

newPerson("Ben"),

newPerson("Alice")

{

Age=9,

Home={Town="C",Country="S"}

}

}

};

#endregion


初始化特性的应用

常量集合
设置单元测试
builder模式
隐式类型数组

MyMethod(new[]{"HE","EH"});
首先构造一个集合,其中包括大括号内所有的表达式的编译时的类型,在这个类型集合中,如果其他所有类型都能隐式转换为其中一种类型,改类型即为数组类型

匿名类型

#region8-4创建具有Name和Age属性的匿名类型对象

vartom=new{Name="Tom",Age=9};//匿名对象初始化程序

Console.WriteLine("{0},{1}",tom.Name,tom.Age);//属性具有和初始化程序中的表达式一样的类型,值在创建匿名对象初始化程序中指定

#endregion


#region8-5用匿名类型填充数组,并计算总年龄

varfamily=new[]//使用隐式类型的数组初始化程序

{

new{Name="Holly",Age=36},//使用匿名对象初始化程序

new{Name="Jon",Age=32}//如果生成不同的类型,编译器无法判断声明数组的类型

};


inttotalAge=0;

foreach(varpersoninfamily)//对每个人使用隐式类型

{

totalAge+=person.Age;

}

Console.WriteLine("Totalage:{0}",totalAge);

#endregion


投影初始化程序

#region8-6从Person对象转换成一个名字和一个成年标志

List<Person>family=newList<Person>

{

newPerson{Name="Holly",Age=36},

newPerson{Name="Jon",Age=23},

newPerson{Name="Jon",Age=23}

};

varconverted=family.ConvertAll(delegate(Personperson)

{returnnew{person.Name,IsAdult=(person.Age>=18)};});//投影初始化程序:如果不指定属性名称,而只指定用于求值的表达式,它就会使用表达式最后一部分作为名称————前提是它只能是一个简单的字段和属性

foreach(varpersoninconverted)

{

Console.WriteLine("{0}isanadult?{1}",person.Name,person.IsAdult);

}

#endregion


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: