Effective C# 第二版 中文翻译之01 有兴趣的可以到我博客看http://blog.csdn.net/andy572633/archive/2011/06/06/6528478.aspx 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 接着翻: 你可以将属性定义成虚的并将它放在接口(Interface)的定义中,隐式属性的语法与此类似。下面代码展示的是定义在一个通用接口(译注:或叫泛型接口,原文:generic interface)中的属性。注意,与隐式属性的语法一样,下面定义的接口中(属性)没有包含任何实际的实现。它定义了任何实现这个接口的类所必须满足的一个抽象目录。public interface INameValuePair<T> { string Name { get; } T Value { get; set; } } 属性是一种全面的、一等的语言特性,它是对对数据进行访问或修改的方法(method)的拓展。任何你能用成员方法(或叫成员函数)实现的的东西,你都能用属性搞定。 属性的访问器(accessors)在类中会被编译成两个独立的方法。在C#中,你可以为get和set制定不同的访问修饰符。这将给你更大的灵活性去控制那些对外暴露为属性的数据成员的访问权限。public class Customer { public virtual string Name { get; protected set; } //具体的实现就省略了吧 } 属性的语法对字简单的数据字段进行了扩展。如果类中包含了被序列化了的元素(典型的就是数组)作为它的接口的一部分,那你可以使用索引器(一组被参数化了的属性,译注:关于索引器自己去看看相关的材料,如果有空的话,我尽量抽空找些出来写在我的博客里)。对于那些要返回一组序列化了的元素的情况,这就非常有用。public int this[int index] { get{return TheValues[index];} set{TheValues[index] = value;} } //通过索引器访问 int val = someObject[i]; 索引器拥有所有与单个属性相同的语言支持。它们可以由你所写的方法来实现,所以在索引器里你可以进行检查或者计算。索引器可以是虚的(virtual)或抽象的(abstract),可以定义在接口中,可以是只读的也可以是读写都可以的。一位的以数字作为参数的索引可以参与到数据绑定中。其它的索引器可以使用非整形的参数去定义图或者字典(如哈希表的字典)。(译注:其实此处也隐含地告诉了索引器是可以使用非整形参数的,这个在学习索引器的时候要注意的)public Address this[string Name] { get{return addressValues[Name];} set{addressValues[Name] = value;} } 为了与C#的多维数组对应,你可以创建多维索引器,各个维度的参数类型可以使相同的也可以是不同的。如下:public int this[int x,int y] { get{return ComputeValues(x,y);} } public int this[int x,string Name] { get{return ComputeValues(x,Name);} } lz原创么,觉得lz语感不错,翻译得很专业。 接着翻:注意,所有的索引器都是用this关键字定义的。在C#中你不能给索引器命名。所以,对于同一个类中的不同索引器,必须定义不同的索引参数列表以避免混淆(译注:参数列表不同包括类型不同和数量不同)。几乎所有的属性的特点都引申到索引器上了:索引器可以是虚的或者抽象的,get和set可以有不同的访问权限。但不能声明隐式的索引器,这点与属性不同。 属性的这些功能都是好的并且有益的,是很不错的改进(译注:作者太啰嗦了)。但是你可能仍然喜欢先定义一些数据成员,直到你需要用到属性那些好处的时候才用属性去替代它们。这貌似是个不错的策略——但它是错误的。看下面的这一段代码: //使用公有的数据成员,这是不好的习惯 public class Customer { public string Name; } 它定义了一个Customer类,里面含有一个Name字段。你可以用普通的成员符号去获取或设置Name的值。 string name = customerOne.Name; customerOne.Name= "This Company,Inc."; 这样确实简单而且直接。你也许在想,以后你用属性来替代Name字段的时候,代码可以不经过任何修改而仍然能够正确运行。嗯,这在某种程度上来讲确实是正确的。属性在访问的时候确实是有意地要表现得像数据成员一样,这也是这种语法后面所隐含的目的(译注:即C#的设计者故意要使属性能像数据成员一样访问)。但属性终究不是数据成员。通过属性访问会产生不同于通过数据成员访问的中间代码(MSIL:Microsoft Intermediate Language)(译注:中间代码,.NET托管代码会先编译成中间代码,然后在运行的时候再实时编译成机器代码。当然,为了提高效率,编译成的机器代码会保留下来。)。 尽管属性和数据成员在源代码上是兼容的,但它们在二进制编码中确是不兼容的(译注:但机器最终执行的确是二进制编码)。所以,很明显,这就意味着当你将一个公有的数据成员改成等效的公有的属性的时候,你必须重新编译所有用到这个公有数据成员的代码。C#将二进制程序集作为一等公民对待(即二进制代码地位比未编译的源代码高)。这个语言的一个目的是你可以单独的发布一个程序集的新版本而不用去更新整个应用程序。但是这样一个简单的从数据成员改为属性的变更却破坏的二进制的兼容性。它使得更新一个已部署的单独的程序集变得更加困难。 当你审视属性的中间代码的时候,你可能会怀疑属性和数据成员间的性能差异。属性的访问不会比数据成员更快,但可能也不会比它慢。JIT编译器(译注:前面所说的在从中间语言编译成机器代码就是由JIT编译器做的。JIT:Just In Time。即只在需要的时候编译)将一些函数做成内联的形式(参见内联函数),对于属性它也是这么做的。当JIT编译器将属性做成内联的时候,对它的访问的效率就和数据成员一样了。即便当属性没有被编译成内联形式的时候,它们之间的效率,也只不过是多了一个微不足道的函数调用而已(特别是在机器硬件速度越来越快的今天,这种差别几乎可以忽略不计)。而且这种情况(属性没有被编译成内联形式)也是仅在极少数情况下才出现的。 属性是这样一种函数,从调用代码来看它表现得与数据成员一样。这就在你的用户的头脑中加进了一些期望。他们将看到属性在访问时表现得好像它就是数据成员一样。但是,那仅仅是它看起来像。你的属性访问者绝对不会辜负这种期望。Get访问者不应当拥有观察方的效果(译注:此处我认为应该是应当拥有,但原文确实是有个大大的not,不知道是不是排版的错误)。Set访问者修改状态,并且用户应该能够看到这些改变。 用户也对属性的性能抱有一定的期待。属性访问,看起来像是数据成员访问。它与简单的数据成员访问间不应该存在明显的性能差别。属性不能花费更长的时间去计算,或者做一些跨程序访问(如数据库查询),或者做一些长时间的操作,这些是与用户对属性的期待背道而驰的。 无论何时,你想要在你的类中对外暴露一些public或protected的数据成员接口时,请使用属性。对于队列和字典可以使用索引器。所有的数据成员都应该是private的,没有例外。这样,你马上就能获得数据绑定的支持,并且在以后你要对这些方法的实现做任何修改都将更加简单。将变量封装到属性中所产生的额外工作量(主要是打字)在现在只不过是花费你一到两分钟。但如果你直到日后发现你需要用属性的时候,才动手去修改的话可能要花上几小时的时间。现在花费少量的时间,将来会为你自己节省大量的时间。 小结:花了几天的业余时间终于将第1节翻译完了,总共有50节,任重而道远啊。所谓万事开头难,英语已经好久不用了,不过相信以后会越来越快的。还是那句话,也许中文版已经出来了,也许已经有别人已经提供翻译得比我更好的版本了,但我还是会坚持下去。主要是锻炼一下自己的毅力和英语能力,同时也与广大网友分享一下我的劳动成果。 零零散散的发比较乱啊,如果大家感兴趣的话可以到我的博客去看:http://blog.csdn.net/andy572633/archive/2011/06/06/6528478.aspx richTextBox 选择文本的问题 ,求助 请问C#可以做什么? 关于DataTable的一个疑惑 QQ自定义表情图片的命名规则是什么 请版主帮忙,WEBSERVICE怎么跟EXE通信呢? update中使用replace()的问题,看看语句对不对? 如何让Timer_Ticker事件不受窗体其他事件的阻塞? 请问做好的软件如何打包发布? DataGrid向数据库传递数据出错 remoting C#中的正则表达式,匹配0-100之间的数字怎么写呢? 关于反射的问题
{
string Name
{
get;
}
T Value
{
get;
set;
}
} 属性是一种全面的、一等的语言特性,它是对对数据进行访问或修改的方法(method)的拓展。任何你能用成员方法(或叫成员函数)实现的的东西,你都能用属性搞定。 属性的访问器(accessors)在类中会被编译成两个独立的方法。在C#中,你可以为get和set制定不同的访问修饰符。这将给你更大的灵活性去控制那些对外暴露为属性的数据成员的访问权限。public class Customer
{
public virtual string Name
{
get;
protected set;
}
//具体的实现就省略了吧
} 属性的语法对字简单的数据字段进行了扩展。如果类中包含了被序列化了的元素(典型的就是数组)作为它的接口的一部分,那你可以使用索引器(一组被参数化了的属性,译注:关于索引器自己去看看相关的材料,如果有空的话,我尽量抽空找些出来写在我的博客里)。对于那些要返回一组序列化了的元素的情况,这就非常有用。public int this[int index]
{
get{return TheValues[index];}
set{TheValues[index] = value;}
}
//通过索引器访问
int val = someObject[i]; 索引器拥有所有与单个属性相同的语言支持。它们可以由你所写的方法来实现,所以在索引器里你可以进行检查或者计算。索引器可以是虚的(virtual)或抽象的(abstract),可以定义在接口中,可以是只读的也可以是读写都可以的。一位的以数字作为参数的索引可以参与到数据绑定中。其它的索引器可以使用非整形的参数去定义图或者字典(如哈希表的字典)。(译注:其实此处也隐含地告诉了索引器是可以使用非整形参数的,这个在学习索引器的时候要注意的)public Address this[string Name]
{
get{return addressValues[Name];}
set{addressValues[Name] = value;}
} 为了与C#的多维数组对应,你可以创建多维索引器,各个维度的参数类型可以使相同的也可以是不同的。如下:public int this[int x,int y]
{
get{return ComputeValues(x,y);}
}
public int this[int x,string Name]
{
get{return ComputeValues(x,Name);}
}
public class Customer
{
public string Name;
} 它定义了一个Customer类,里面含有一个Name字段。你可以用普通的成员符号去获取或设置Name的值。 string name = customerOne.Name;
customerOne.Name= "This Company,Inc."; 这样确实简单而且直接。你也许在想,以后你用属性来替代Name字段的时候,代码可以不经过任何修改而仍然能够正确运行。嗯,这在某种程度上来讲确实是正确的。属性在访问的时候确实是有意地要表现得像数据成员一样,这也是这种语法后面所隐含的目的(译注:即C#的设计者故意要使属性能像数据成员一样访问)。但属性终究不是数据成员。通过属性访问会产生不同于通过数据成员访问的中间代码(MSIL:Microsoft Intermediate Language)(译注:中间代码,.NET托管代码会先编译成中间代码,然后在运行的时候再实时编译成机器代码。当然,为了提高效率,编译成的机器代码会保留下来。)。 尽管属性和数据成员在源代码上是兼容的,但它们在二进制编码中确是不兼容的(译注:但机器最终执行的确是二进制编码)。所以,很明显,这就意味着当你将一个公有的数据成员改成等效的公有的属性的时候,你必须重新编译所有用到这个公有数据成员的代码。C#将二进制程序集作为一等公民对待(即二进制代码地位比未编译的源代码高)。这个语言的一个目的是你可以单独的发布一个程序集的新版本而不用去更新整个应用程序。但是这样一个简单的从数据成员改为属性的变更却破坏的二进制的兼容性。它使得更新一个已部署的单独的程序集变得更加困难。 当你审视属性的中间代码的时候,你可能会怀疑属性和数据成员间的性能差异。属性的访问不会比数据成员更快,但可能也不会比它慢。JIT编译器(译注:前面所说的在从中间语言编译成机器代码就是由JIT编译器做的。JIT:Just In Time。即只在需要的时候编译)将一些函数做成内联的形式(参见内联函数),对于属性它也是这么做的。当JIT编译器将属性做成内联的时候,对它的访问的效率就和数据成员一样了。即便当属性没有被编译成内联形式的时候,它们之间的效率,也只不过是多了一个微不足道的函数调用而已(特别是在机器硬件速度越来越快的今天,这种差别几乎可以忽略不计)。而且这种情况(属性没有被编译成内联形式)也是仅在极少数情况下才出现的。 属性是这样一种函数,从调用代码来看它表现得与数据成员一样。这就在你的用户的头脑中加进了一些期望。他们将看到属性在访问时表现得好像它就是数据成员一样。但是,那仅仅是它看起来像。你的属性访问者绝对不会辜负这种期望。Get访问者不应当拥有观察方的效果(译注:此处我认为应该是应当拥有,但原文确实是有个大大的not,不知道是不是排版的错误)。Set访问者修改状态,并且用户应该能够看到这些改变。 用户也对属性的性能抱有一定的期待。属性访问,看起来像是数据成员访问。它与简单的数据成员访问间不应该存在明显的性能差别。属性不能花费更长的时间去计算,或者做一些跨程序访问(如数据库查询),或者做一些长时间的操作,这些是与用户对属性的期待背道而驰的。 无论何时,你想要在你的类中对外暴露一些public或protected的数据成员接口时,请使用属性。对于队列和字典可以使用索引器。所有的数据成员都应该是private的,没有例外。这样,你马上就能获得数据绑定的支持,并且在以后你要对这些方法的实现做任何修改都将更加简单。将变量封装到属性中所产生的额外工作量(主要是打字)在现在只不过是花费你一到两分钟。但如果你直到日后发现你需要用属性的时候,才动手去修改的话可能要花上几小时的时间。现在花费少量的时间,将来会为你自己节省大量的时间。 小结:花了几天的业余时间终于将第1节翻译完了,总共有50节,任重而道远啊。所谓万事开头难,英语已经好久不用了,不过相信以后会越来越快的。还是那句话,也许中文版已经出来了,也许已经有别人已经提供翻译得比我更好的版本了,但我还是会坚持下去。主要是锻炼一下自己的毅力和英语能力,同时也与广大网友分享一下我的劳动成果。
http://blog.csdn.net/andy572633/archive/2011/06/06/6528478.aspx