发表评论
上个星期去上海书城,看见了这本书,然后翻看了一部分,实在是太精彩了,内容正如其名《你必须知道的.NET》,让我们可以更深入的了解一些原理,谢谢涛哥的无私奉献!虽然现在生活比较忙,但是我会仔细得读完她,有不懂之处到时还望多多指教:)
我最近购买了这本书,并看了前两个章节,但有些内容反复看了几遍仍然有些不明白的地方,也许是基础太差的原因,我想问的是如果在阅读过程中有疑惑的地方在哪里可以得到咨询,邮件咨询吗?或是在该支持中心?
@Anytao
谢谢楼主的回复,希望今后出更多的好书。
请问涛哥,学.net的哪里就业好些啊
还有最主要的是学些什么东西呢?
#106楼[
楼主]2008-05-12 22:14 |
@A.feng..
谢谢你的鼓励和关注。这本书倾注了近8个月的时间和精力,我把自己认为重要的东西做以挖掘,就是希望有更多的技术开发者能够投入更多的精力在最应该投入的基础上,再来举一反三的轻松应对其他问题。
谢谢你的支持:-)
#107楼[
楼主]2008-05-12 22:17 |
@jr573
谢谢您的关注,基础其实正是应该首先被关注的环节,否则只会事倍功半,饶有徒劳。
如果您有任何书中或者书外相关的话题,皆可通过支持中心,或者邮件与我联系,当然我推荐以邮件进行沟通,因为平常太忙了,只有空闲的时候才可以回复。我的支持邮件在支持中心有,可以查看:-)
#108楼[
楼主]2008-05-12 22:24 |
@aizhu
呵呵,这是个两难的话题。在我看来,从事技术研究其实并非非常有“钱”途的职业,最重要的是个兴趣问题,也只有兴趣过关才能在浩瀚如海的技术森林中游刃有余,否则很快就会被淹没。
所以,关于选择,我理解最重要的看个人的理想和兴趣。而对于.NET技术来说,每个应用的领域,我觉得都值得探索和挖掘,Moss、Mobile、ASP .NET、Biztalk等等各个方向研究下去都能找到发光的地方。归根结底,选择要根据自己的兴趣,但是不管哪个应用方向,对于.NET Framewok和CLR的理解都一定是个基础,也最终决定了你在各个领域应用中所站的高度。
#109楼[
楼主]2008-05-12 22:26 |
@一叶孤鸿
关于嵌入式开发,恕我没有太多方面的研究,所以不便回答这个问题,不过可以介绍你向葛涵涛、马宁这几位了解相关的情况,他们是这方面的专家,而且非常热心,具体地址可以在cnblogs中搜索即可找到。
谢谢关注:-)
王涛大哥,刚才本想睡觉的,但是睡前又仔细回味了今天阅读的一些内容,发现有些问题不能理解,是第2章的OCP和DIP内容的,然后怎么也睡不着,索性起来给你发邮件,但愿你能在不忙的时候抽空指点一下,不胜感激!
#112楼[
楼主]2008-05-13 23:41 |
@A.feng..
已经回复邮件,谢谢你的讨论:-)
#113楼[
楼主]2008-05-13 23:42 |
@xiaoyi1234
哈哈,应该是我说感谢,呵呵,大家的支持对我是莫大的动力。
十分感谢,您的认真态度实在让我感动,请允许我小小的抒情一下:),最后我想可能之前我没能准确的表达自己的意思,所以就更详细的重新描述了一遍,麻烦王涛大哥过目:)
#116楼[
楼主]2008-05-14 23:59 |
@A.feng..
呵呵,你太客气了,也谢谢你的讨论,邮件已回:-)
#117楼[
楼主]2008-05-15 00:00 |
@一叶孤鸿
呵呵,欢迎常来这里看看,对于嵌入式的理解也会有所帮助:-)
突然间理解一些东西的感觉实在是太美妙了,今晚我肯定能睡得很香,也祝您有个好梦:)
#120楼[
楼主]2008-05-23 14:41 |
@A.feng..
谢谢,A.feng的执着,近来非常的忙碌,所以没有及时回复,还望见谅。
关于这个问题,我想可能把书中的全文写出来,可能理解就清楚了:
建议使用String.Compare方式进行比较,尤其是非大小写敏感字符串的比较,在性能上更加有效。
具体的解释可以详读原文,同样针对你的测试数据,如果进行非大小写敏感的比较时,flag = strA.ToUpper() == strB.ToUpper();在性能上会有明显的差别。
不过,作为最常见的比较手段,以==来进行大小写敏感比较还是推荐的:-)
哈哈,谢啦,果然如此,原来是我没能理解这段话的含义:)我的机器上,测试10W次,ToUpper()消耗了143ms,而string.Compare()只用了48ms..thanks a lot^^
有一封新的邮件,注意查收哦,呵呵,祝周末愉快!:)
#123楼[
楼主]2008-05-23 22:27 |
@A.feng..
呵呵,谢谢你的参与,细想起来,那块的表达虽不构成勘误,但也有些欠妥,你提醒的很对,有些地方需要精雕细琢:-)
您好Anytao,在读书时有个疑问,P14页这么说的“对象一经创建,会首先找到其父类Bird,并为其字段分配存储空间,而Bird也会继续找到其父类Animal,为其分配存储空间”
不是应该先找到其父类Bird,然后再找到父类Animal,这时先给Animal分配存储空间,然后再给Bird分配空间,最后才是给自己分配存储空间吗?我在单步调试时发现构造函数是这么调用的,不知这样说是否有问题:)
#125楼[
楼主]2008-05-27 11:30 |
@j.Nan
你好,谢谢你的关注。实际上,对象创建是一个及其复杂的过程,在《你必须知道的.NET》第5章有专门详细的论述,你可以找到相应的章节详查:-)
在对象过程中有几个大的阶段,你提到的部分就是其中两个主要阶段:内存分配和初始化,所以上述过程是两个阶段,不可混为一谈。关于内存分配,实际上的分配是一次性完成的,而CLR则会根据对象的继承层次进行向上遍历,来计算应该分配的内存大小,此处的过程实际是描述了这个遍历的基本过程;分配内存之后,将进行初始化动作,也就是你根据单步调用时考察的一样。
详细的情况可以参见《你必须知道的.NET》5.2 对象创建始末
谢谢Anytao,那么其实我描述的应该是内存分配时的情形,之后才是从父类到子类依次调用构造函数进行初始化了,谢谢你的回复。
#127楼[
楼主]2008-05-27 17:54 |
@j.Nan
呵呵,也谢谢你的讨论,详细的情况《你必须知道的.NET》5.2 对象创建始末可以给你满意的答案:-)
#129楼[
楼主]2008-06-04 21:28 |
我已经买过这本书了,但是觉着在公司的时候还想看个电子版的,不知道是否可以。我的邮箱是dongyongjing@163.com。如果可以的话麻烦给个电子版的。谢谢。
#131楼[
楼主]2008-06-15 16:10 |
@Edwin dong
很抱歉,因为有一些合同约定,所以电子版还不便公布,涉及到其他的一些问题,不是我能完全决定的事情。
非常抱歉,希望见谅:-)
#133楼[
楼主]2008-06-19 23:54 |
@agp001
呵呵,谢谢捧场,卓越是个好选择,希望能帮助到你:-)
#135楼[
楼主]2008-06-23 23:44 |
@RainSky
没有问题,随时欢迎讨论:-)
问问弱弱的问题
关于第一章1.2里面继承那里
public class BirdAdapter : ITweetable
{
private Bird _bird;
public BirdAdapter(Bird bird)
{
_bird = bird;
}
public void ShowType()
{
_bird.ShowType();
}
public void ToTweet()
{
//为不同的子类实现不同的ToTweet行为
}
}
//为不同的子类实现不同的ToTweet行为
这里是怎么为不同的子类实现不同的ToTweet行为的呢?请Anytao指点一下。
#137楼[
楼主]2008-06-24 23:27 |
@AgpSky
首先,非常感谢你的“悦”读,其实对于Adapter模式,还有很多“话”要说,但是限于篇幅,欲言又止。不过,你提的问题,的确需要一点篇幅来继续讲述,因为绝对值得探讨。
接下来讨论正题:
首先可以通过在运行时判断类型的方式来对不同的子类实现不同的ToTweet方法,例如
public void ToTweet()
{
if (_bird is Chicken)
//执行Chicken的ToTweet操作
if(_bird is Eagle)
//执行Eagle的ToTweet操作
}
显然,这是一个解决的办法,为不同的子类实现不同的ToTweet行为的目的是达到了,但是同时也是一个不折不扣的僵化设计。那么,如何解决这一问题呢,因为_bird的类型是在运行时决定的,所以加入条件判断就在所难免。因此,只能牺牲类的数量来解决这一问题,即我们可以为Chicken和Eagle实现不同的面向对象的Adpater模式,例如
public class ChickenAdapter : ITweetable
{
private Chicken _bird;
public ChickenAdapter (Chicken chicken)
{
_bird = chicken;
}
public void ShowType()
{
_bird.ShowType();
}
public void ToTweet()
{
//为Chicken实现不同的ToTweet行为
}
}
其他的同理按照这种方式进行来实现。
行文至此,我们知道要想避免对象创建的条件判断,就有必要提供工厂模式来解决这个问题,至于如何去做,你可以参考相关的资料或者进行一点深入的思考,是不难理解的。
所以,针对不同的情况,类的Adapter模式和对象的Adapter模式都是各有利弊的,关键看你如何去应对。
谢谢:-)
@Anytao
谢谢您的解释。
也就是说和工厂模式结合以后就可以达到更理想的效果了。对吗?
#140楼[
楼主]2008-06-25 09:59 |
@bjyuxiao
随时欢迎
#141楼[
楼主]2008-06-25 10:00 |
@AgpSky
呵呵,还是要视具体的情况而定,没有不变的规则。在对象的Adpater模式中,如何避免条件判断,引入工厂模式是必要的。。。
谢谢
嘿嘿~~~明天准备去买这本书了哦~~~,来报告一哈~~~
Congratulations Anytao!
刚刚上网偶然间看到你的新书《你必须知道的.NET》问世了。就像宝宝呱呱落地一样,这本书凝结了你的心血,你是辛苦的,看到这本书,我也感觉到你是幸福的。八月怀胎,几年的积累酝酿,多年的感情的培养,结晶诞生的那一刻,你一定会满盈泪花,充满激情与喜悦。虽然你是男人,我却体会到你对这本书有做母亲般的温柔,那是可爱的,也是值得所有人去尊敬的。
作为同学,更作为朋友,我祝贺你。为你骄傲。
这本书我看了第1,2章。写的非常好啊。特别是那个万能加载器小生体会颇深。感谢作者写出这么好的一本书
#145楼[
楼主]2008-06-29 20:01 |
@Shouke_du
哈哈,谢谢支持,各大书店和网店均有销售:-)欢迎来此交流
#146楼[
楼主]2008-06-29 20:04 |
@高泽东
嘿嘿,不好意思,你说的太肉麻了。写书是一种折磨,也是一种幸福,如炼狱一般,千锤百炼之后能够收获更多的所得。
谢谢兄弟的祝贺,谢谢朋友的支持,持续努力才是最好的致谢:-)
#147楼[
楼主]2008-06-29 20:05 |
@疯流成性
嘿嘿,谢谢支持。Anytao和《你必须知道的.NET》支持中心将随时欢迎读者的评论、勘误和交流:-)
看了很多勘误,所以想在第二版时再买,什么时候出第二版呢?
mvp的名字.......
tao wang........逃亡.......
#150楼[
楼主]2008-07-03 23:36 |
@finer
很抱歉有这些无意之失,第二版还没有进入计划,可能还得段时间,谢谢你的关注。
#151楼[
楼主]2008-07-03 23:37 |
@your english name is so funny
呵呵,Wang Tao就是Wang Tao,我没有英文名字,你可以叫我Wang Tao:-)
#153楼[
楼主]2008-07-09 01:54 |
@AlexLiu
本书定位是在基础之上进行提高的阶段,可以和基础学习同步进行:-)
我在csdn上看的试读,发现了一些错误和使人误解的地方:
第一章 1.2
“类Chicken生成方法列表时,首先将Bird的所有方法复制一份”
>>
不是所有方法而只是虚方法
-----------------------------------------------------
第五章 5.2
对于分配在堆栈上的局部变量来说,操作系统维护着一个堆栈指针来指向下一个自由空间的地址,并且堆栈的内存地址是由高位到低位向下填充,也就表示入栈时栈顶向低地址扩展,出栈时,栈顶向高地址回退以下例而言:
public void MyCall()
{
int x = 100;
char c = 'A';
}
当程序执行至MyCall方法时,假设此时线程栈的初始地址为50000,因此堆栈指针开始指向50000地址空间。方法调用时,首先入栈的是返回地址,也就是方法执行之后的下一条可执行语句的地址,用于方法返回之后程序继续执行,如图5-1所示。
然后是整型局部变量x,它将在栈上分配4Byte的内存空间,因此堆栈指针继续向下移动4个字节,并将值100保存在相应的地址空间,同时堆栈指针指向下一个自由空间,如图5-2所示
>>
不存在“堆栈”这个东西,只有“栈”和“堆”,再者.net的线程栈和操作系统上的是不一样的,对于每一个栈帧记录来说是有高低之到底地址。而局部变量保存在局部变量表中不一定是这个规则。
在csdn上有人发贴说.net有栈,堆栈,堆三种数据结构,我觉得你上面这段话的描述给人已非常大的误导。
-----------------------------------------------------------
还是5.2节:
SyncBlockIndex,用于线程同步,每个对象创建时也包含该附加成员,它指向一块被称为Synchronization Block的内存块,用于管理对象同步,同样占用4个字节的内存空间
>>
首先你那个描述托管对象的图有问题,syncblockindex是在对象地址-4的位置上而不是在typehandle的后面,再者syncidx并不一定指向syncblk,在用于同步时是一个指向SyncBlk Entry的slot号,在仅用于GetHashCode时是直接指向syncblk的
-----------------------------------------------------------
还是5.2节:
(a)CLR按照其继承层次进行搜索,计算类型及其所有父类的字段,该搜索将一直递归到System.Object类型,并返回字节总数,以本例而言类型VIPUser需要的字节总数为15Byte,具体计算为:VIPUser类型本身字段isVip(bool型)为1Byte;父类User类型的字段id(Int32型)为4Byte,字段user保存了指向UserInfo型的引用,因此占4Byte,而同时还要为UserInfo分配6Byte字节的内存
(b)实例对象所占的字节总数还要加上对象附加成员所需的字节总数,其中附加成员包括TypeHandle和SyncBlockIndex,共计8字节(在32位CPU平台下)。因此,需要在托管堆上分配的字节总数为23字节,而堆上的内存块总是按照4Byte的倍数进行分配,因此本例中将分配24字节的地址空间。
>>
这个我不知道你是笔误还是什么,在没有给User类的user字段赋值的情况下VIPUser的大小是:8 + 4(UserInfo引用) + 4(id) + 1(isVip) = 20(17补齐到20)如果new出了UserInfo则是20 + 8 + 6 = 36(34补齐到36)
5.4.2 性能条款:
Item10:尽量在子类中重写ToString方法。
ToString方法是System.Object提供的一个公有的虚方法,.NET中任何类型都可继承System.Object类型提供的实现方法,默认为返回类型全路径名称。在自定义类或结构中重写ToString方法,除了可以有效控制输出结果,还能在一定程度上减少装箱操作的发生
>>
只有struct会造成装箱,而且GetHashCode,Equals不重写也会造成装箱
#156楼[
楼主]2008-07-15 01:12 |
#157楼[
楼主]2008-07-15 01:15 |
@fuadam
关于ToString重写的问题,对Struct来说可以有效避免装箱,而对于Class则可以更好的控制输出,所以本条建议是基于这两点而言的:-)
弱弱的问下
P5:面向接口的编程是以接口方式来抽象变化
但是接口都是把相同的部分给抽象出来,怎么说是抽象变化呢?
而我们在实际项目中也都是把公有的,相同的部分提取出来,所以这里有点不理解^_^
楼上这条评论怎么发通知到我的油箱了。
所谓抽象变化这个词 可能要这么理解,在变化中抽象出来稳定的东西。
#161楼[
楼主]2008-07-15 23:44 |
@Marklee
封装变化,面向抽象编程,需要了解的是什么是变化,而为什么要抽象?
将变化这种不稳定,以抽象这种稳定的东西,暴露给外部使得耦合基于稳定而实现是剥离系统关系达到优良设计的基本思路。
例如,对象工厂模式解决了对象创建的变化,而Command模式则应对请求的变化。假设一个可扩展的文件系统,开始提供对于doc文件的支持:
public class DocFile
{
public Open();
}
而等到需求更多的要求时,ImageFile、MusicFile等等,
public class MusicFile
{
public Start();
}
文件的打开对外部系统就是个“变化”,那么以接口进行封装,就是对这种变化的应对:
interface IOpen
{
void Execute();
}
#162楼[
楼主]2008-07-15 23:46 |
@暗香浮动
凡事订阅的,都会发回复邮件:-)
#163楼[
楼主]2008-07-15 23:46 |
@jeffery8110
谢谢
语言柔和,看上去到不像一本技术类的书籍有点像朋友之间的调侃,我很喜欢这种表达方式!我刚买了一本不到4天就跟随我的电脑包(包括笔记本)一起被小偷给偷了,郁闷之及,回来后又买了一本!正在学习中!!
#165楼[
楼主]2008-07-25 21:18 |
@阿豹
很遗憾丢了本,现在车上太挤,还是多小心呀。
同时感谢的你支持,有想法和疑问随时可以通过邮件沟通,谢谢:-)
我在看书中第二部分时,有点困惑,就是那么多的IL指令都需要记住么?对IL到底需要了解到什么程度呢?
张涛大哥的态度,让我钦佩,打算晚上买一本好好研读,如有不懂之处,还请您指教。
#168楼[
楼主]2008-08-14 17:21 |
@Vincent Zhou
感谢你的支持。
对于IL,我觉得够用就行,掌握常用的指令,其他的可以通过查找来及时补充,完全没有必要记住所有的IL指令,其实也记不住。
所以,学习讲求一定的方法,例如你要探讨beforefieldinit对于性能的影响时,再仔细了解beforefieldinit其本质的意义就行,平常的情况下只要知道有这么一个指令标记。
以上,仅仅是我的感觉,仅供参考;-)
#169楼[
楼主]2008-08-14 17:22 |
@tianh
呵呵,不敢称大哥,谢谢支持。
另外,我不姓张,叫我Anytao就好了:-)
作为.NET开发人员,深入了解自己掌握的工具很重要。
这本书给了我一个更清晰的.NET.
#171楼[
楼主]2008-09-18 20:41 |
@蜡笔小王
呵呵,两个小王,两本小书,一种心得,一种分享:-)
您好~是不是需要先把c#的所有东西都掌握了才能看懂这本书啊??
#173楼[
楼主]2008-10-05 16:57 |
@lvnana
呵呵,并非如此,技术学习的过程是一个循序渐进的过程,一般来说,我更喜欢跳着阅读,取己所需,这样读起来更有针对性。
本书而言,一方面可以系统的了解.NET的相关知识,另一方面,完全可以抛开章节的限制,对某个技术角度进行深度探索。
:-)
终于收到书了,看了感觉很好,书不错,支持!
不过发现一错别字,呵呵,第12页第7行应该是“用于显示鸟类的毛色”被写成了“用于现实鸟类的毛色”,当然这不影响阅读,只是提下而已。
前几天买了这本书,今天有空翻翻,有个很菜问题想问一下,书中p14页说到过一个 typehandle ,有点搞不清楚,能否给我讲讲,谢谢!
#176楼[
楼主]2008-11-02 17:16 |
@蓝色海岸线
谢谢更误,书写错误:-)
#177楼[
楼主]2008-11-02 17:17 |
@艾轩
您好,关于TypeHandle在本书5.2节 “对象创建始末”中有所论述,你可以到P174页关注相关的内容,谢谢:-)
这本书确实写的很好!把面向对象编程写的很生动,很贴近与生活中的对象,面向对象编程麻,更贴近生活中的的对象理解认识才能更好的掌握。我很支持这本书!
#179楼[
楼主]2008-11-11 22:05 |
@陶勇强
谢谢支持,对于面向对象而言,其实越是深刻越是生活。你可以以“面向抽象”来阐释所有的精髓,但一定需要以更贴切的实例来阐释思想。
最近一直盲目的想找一些关于.net的书籍看。来逛了逛园子。发现了这本书,评价很好。
Anytao很不错。服务也挺棒的。我也买本去。
#183楼[
楼主]2008-11-28 11:27 |
@quinbny
呵呵,谢谢啦,可以来此交流:-)
#184楼[
楼主]2008-11-28 11:27 |
@quinbny
我试过了,是可以下载的,你可以再换换浏览器看看:-)
#185楼[
楼主]2008-11-28 11:28 |
@Cnddb
呵呵,谢谢支持。
看到第7章了!越看越有味!,这书真的不错,现在我们公司还在用VS05开发!
自己在学习C#3.5里面的东东!嘿嘿!有机会把不明白的问题来请你指教一下,要多交流交流饿!嘿嘿!
怎么买本书网站的价格都有所不同啊,我该在那网站买好点呢
#188楼[
楼主]2008-12-01 23:49 |
@陶勇强
呵呵,谢谢支持,随时讨论:-)
#189楼[
楼主]2008-12-01 23:50 |
@wangcong
几家网店都不错,当然更推荐博客园网店:-)
支持,每天晚上都看书学习,不过有很多地方要看好几遍
#191楼[
楼主]2008-12-02 22:50 |
@love&tiger
每天都学习,都是好同志:-)
@Anytao
值类型不具有多态性,这个如果一个值类型MyStruct : public IMyInterface{}
函数void MyFunction(IMyInterface)调用时候传入new Mystruct,这个算不算多态!
@iTech
using System;
using System.Collections.Generic;
using System.Text;
namespace MyTest
{
interface MyInterface
{
void Print();
}
struct MyStruct : MyInterface
{
void MyInterface.Print()
{
Console.WriteLine("MyStruct's Print!");
}
}
class Program
{
static void MyFuntion(MyInterface my)
{
my.Print();
}
static void Main(string[] args)
{
MyFuntion(new MyStruct());
}
}
}
这个可不可算为多态!
#195楼[
楼主]2009-02-10 11:35 |
@iTech
呵呵,皮肤正在考虑修改
#196楼[
楼主]2009-02-10 11:38 |
@iTech
你指出的情况,算是值类型的多态,但是值类型没有方法表的概念,所以在本质上这个值类型会被装箱为引用类型,通过Typehandler执行方法表,实现多态。
对于集合的分类:
实现了ICollection的为有序集合,实现了IList的为索引结合!
我觉的这个是不是搞反了哦?
#198楼[
楼主]2009-02-13 13:33 |
有序集合,表示了插入集合的元素顺序决定了其检索顺序,例如Stack、例如Queue,这些集合只实现了ICollection;
而索引集合,表示集合元素可以由其索引检索,这些集合实现了IList接口。所以IList中就提供了IndexOf方法来返回其索引数,概念上是没有问题的。
请问一下
未能加载文件或程序集“CrystalDecisions.ReportAppServer.ClientDoc, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304”或它的某一个依赖项。系统找不到指定的文件。
是要装Version=10.5.3700.0的报表查看器吗?装了就ok吗?
谢谢
第一版本的书 已经读了 感觉挺好的,楼主继续努力呀!
114页 Grandson类中,
public override void DoVirtualWork() {...}这个没问题,但在后面的分析中
117页,第三四行:
aGrandSon.DoVirtualWork(),对应于....,同样是由于new关键字的阻断作用...
前后对比起来,Grandson类中的"DoVirtualWork"定义中并无new关键字,为何后面的分析中有"同样是由于new关键字",是否矛盾?