关于发展深厚的编程知识


136

有时,我会看到有关堆栈溢出的边缘情况和其他怪异的问题,这些问题很容易被Jon Skeet和Eric Lippert之类的人回答,这显示出对该语言及其许多复杂性深入了解,例如:

您可能会认为,要使用foreach循环,要迭代的集合必须实现IEnumerableIEnumerable<T>。但是事实证明,这实际上不是必需的。所要求的是,集合的类型必须具有称为的公共方法GetEnumerator,并且必须返回具有称为的公共属性getter CurrentMoveNext返回a 的公共方法的某种类型bool。如果编译器可以确定满足所有这些要求,则将生成代码以使用那些方法。仅当不满足这些要求时,我们才会检查对象是否实现IEnumerableIEnumerable<T>

这是很酷的事情。我能理解为什么埃里克知道这一点。他在编译器团队中,所以他必须知道。但是那些表现出如此深厚的知识而不是内部人的人呢?

凡人(不是C#编译器团队成员)如何找到类似这样的东西?

具体来说,这些人是否使用方法来系统地扎根此类知识,对其进行探索并对其进行内部化(使其自己拥有)?


10
我认为这尤其是开源软件大放异彩的地方。能够一直进入框架/系统/库,这是很好的。当我使用Qt时,比起使用WinForms时,我曾经有一种更好地了解框架内部的方法。
Vitor Py

2
除了不在特殊人群面前显得愚蠢之外,您什么时候需要知道这个具体示例?他们白痴证明了这一点。除此之外,Effective C#,Java,C ++等系列可能还包含一些很棒的东西。埃里克·利珀特(Eric Lippert)的博客也是一个很好的来源。总的来说,我们常常不知道不知道什么,所以正如他们所说的“活一百年,学习一百年,死傻瓜”。
Job

26
值得付出努力吗?我是双语人,正在尝试学习其他几种口头语言。我参加了一些数学课程,但还不够。我想学习如何像样的打网球,学会用蝶泳游泳。我想旅行更多。我想学习一些Clojure。我不希望成为一种语言的专家,拥有数学博士学位,每周在迈克尔·菲尔普斯(Michael Phelps)等游泳池度过30个小时。Lippert和Skeet的知识是由于他们投入了大量精力在一件(或几件)事情上努力,而在其他经验上则错失良机。也许换工作?
工作

10
“我能理解为什么Eric知道这一点;他在编译器团队中,所以他必须知道。” -他知道这是因为他首先考虑了。我怀疑他必须“发现”它的工作原理是这样的:)
亚历克斯·十·布林克

10
@Alex:自从我们开始实际构建C#3的实现以来,我实际上只从事C#的工作。“ foreach”规范是在此之前写的六年。我仍然每天都在探寻有关该语言的疯狂历史事物。例如,我今天了解到,对于代表来说,(((A + B)+ C)-(A + C)= A + B + C,但是((A + B)+ C)-(B + C)= A 。 奇怪的!
埃里克·利珀特

Answers:


167

首先,感谢您的客气话。

如果您想深入了解C#,那么拥有语言规范,十年的设计说明,源代码,Bug数据库以及紧邻大厅的Anders,Mads,Scott和Peter 无疑是一个优势。我当然很幸运,对此毫无疑问。

但是,即使没有这些优势,也仍然可以深入了解该主题。

回到Microsoft时,我正在使用Internet Explorer 3附带的JScript解释器。当时,我的经理告诉我了一些我所获得的最佳建议。他说,他希望我成为Microsoft在JScript语言的语法和语义方面的公认专家,并且我应该针对JScript的这些方面寻找问题并予以回答,以解决这个问题。特别是回答我不知道答案的问题,因为那是我会从中学习的问题。

显然,StackOverflow和其他公共问答论坛就像是从火水杯中喝水一样。那时,我认真地阅读了comp.lang.javascript和我们内部的Microsoft“ JS User”论坛,并听从了我经理的建议:当我看到一个关于我不知道答案的语言语义的问题时,我做到了我的生意找出来。

如果要进行这样的“深潜”,则必须谨慎选择。我这一天是非常无知的浏览器对象模型的工作原理。由于最近几年我一直专注于成为C#语言专家,因此我对基类库中各种类的工作方式一无所知。我很幸运,因为我有一份工作可以奖励特定的深造知识。如果您的工作或才干更适合成为通才,则深入研究可能对您不起作用。

撰写博客也很有帮助;通过要求我向其他人解释复杂的主题,我不得不一直面对自己对各种主题的理解不足。


14
不要拖延这个话题,但是在阅读了这个答案之后,我很好奇为什么您在这里或Stack Overflow上没有问任何问题。此时,您的同事,博客等是否足以满足您的需求?是否有比我们应该知道的更好的资源?
马修(Matthew)

6
也许您误解了他在说什么。违反直觉,他不是在问问题以学习东西,而是在回答问题。
鸣叫

65

在对话的“专家”一到两次之后,我可以告诉你,很多时候,您对编程语言或系统的“深刻了解”通常是由于最近“专家”努力争取的结果一个月来解决完全相同的问题。在论坛上,人们可以选择要回答的问题尤其如此。甚至Jon Skeet和Eric Lippert之类的人也必须一次学习世界。他们一次与其他人一样,只接受一个概念的知识。


1
很好的一点。在进行长时间的研究时,我经常会发现由于我今天早些时候学到的东西,我现在可以回答一些问题。
马修(Matthew)

47

释义瑜伽士巴赞:

“如果您想学习一些东西,请阅读;如果您想了解一些东西,请撰写;如果您想掌握一些东西,请对其进行 编程。”

编程就像最终的教学挑战。教计算机做某事需要您非常了解自己的东西-否则您将学会精通它。

例如,如果您想学习物理,请编写一个物理引擎。如果您想学习国际象棋,请编写国际象棋游戏。如果您想学习更深的C#知识,请编写C#编译器(或其他工具)。


2
编程也是一种以最明确的方式进行写作的适度尝试(当然要被人们阅读)。
vpit3833 2011年

4
在我阅读国际象棋示例之前,那句话听起来很深刻。不幸的是,对国际象棋AI进行编程并不能使您成为更好的国际象棋玩家(基本上是在Min-Max树中进行搜索)。仍然+1
Bughi 2012年

1
@bughi也许您可以掌握规则:D
Julio Rodrigues

@bughi,“编程它”是一个非常广泛的术语,并不总是与编写代码有关!开箱即用。
Nitesh Verma

25

据我所知,学习此方法的方法是:

  • 从像Eric Lippert这样的人那里读到它
  • 亲身体验然后解决问题。

第二种方法可能需要更长的时间,但可能会导致更深刻的理解(但不总是如此)。


17
或两者。[15个字符]
Michael K

23

我会说:

在可以完成大多数常见任务的水平上学习了相对有用的语言堆栈(完成一项工作所需的语言)之后,请停止学习更多的语言,直到您至少学习了一种语言为止。我认为,目前我们行业的问题之一是,人们在学习其他语言之前只学习该语言的前5-10%。一旦具备了完成一项工作中最常见任务的能力,便可以开始深入研究一件事。(您可以在达到一定深度后回到广度,然后在两者之间来回移动。)

为更复杂,更艰巨的任务提供志愿服务,使您不得不深入解决问题。如果没有工作,请寻找开源任务来做或开始从事个人项目,这将使您不得不深入。如果您的工作没有有趣的问题,请考虑寻找更具挑战性的工作。

阅读一种语言的高级书籍(例如,对于SQl Server,这将包括有关性能调优和数据库内部知识的阅读),而不是在30天的学习类型中学习X。

在这里和其他需要阅读的地方阅读有趣的问题,并尝试自己解决一些问题。如果您想学习,尝试解决一些问题,而不先阅读其他答案。即使已经回答了该问题,如果您自己找到答案,您也会学到更多。您甚至可能找到比问题答案更好的答案。

问一些较难的问题。评估给出的答案,而不仅仅是使用它们。确保了解答案为何有效或无效。使用这些答案作为研究的起点。

从该领域的知名专家那里找到一些不错的技术博客,然后阅读它们。

完成学习后,停止扔掉您的知识。学会保留。大多数专家不必查找通用语法。他们不必每次都遇到问题时就重新发明轮子,因为他们记得自己以前是如何解决类似问题的。他们可以将点连接起来,看看他们两年前做过的问题X与现在遇到的问题Y有什么相似之处(令我惊讶的是,似乎很少有人能够那样做)。因此,他们有更多时间可用于研究更多有趣的主题。


一个不错的答案。但是我不禁要问,如何在保留知识和连接点上变得更好?

我建议您记下所学内容。我开始在Evernote中进行此操作,几年后,我发现自己可以依靠自己的笔记了。慢慢地,我也可以将我的笔记制作成演示文稿了,我准备随时通知。
Shivasubramanian A

9

您可以从深入研究想要成为专家的语言规范开始。例如:


3
好的答案-例如,链接的C#规范的15.8.4节介绍了的实现foreach,并阐明了Eric Lippert引用的博客文章中描述的行为。一旦有人发现自己的思维像“我想知道的foreach 真正的工作。”这将是开始寻找的好地方。
2011年

6

获取Reflector或任何其他反编译器(因为现在需要付款),然后开始打开一些最常用的.NET库以了解内部原理。与通过C#编写的CLR之类的书结合在一起,您会学到很多(比我们大多数人从事常规工作的要深)。


5
实际上,我对BitConverter类进行了此操作,并发现了IsLittleEndian系统特定的标志。
罗伯特·哈维

大声笑。为isLittleEndian +1
鲁迪

4

我花comp.lang.c++.moderated了几年时间在C ++中学习了这类知识,即使那时我并没有真正努力地编写代码。不过,我不确定我能说我是多么的上师。

我认为可以从两种知识中了解一种编程语言:

  1. 了解有关语言的琐事,并知道如何避免陷阱。
  2. 知道如何有效地解决问题。

只能通过使用该语言进行编程并查看其他人的代码来实现数字2,但是可以通过花大量时间在其讨论论坛上阅读该语言,查看人们提出的各种问题以及如何解决该问题来实现数字1。答案是。StackOverflow也是一个很好的地方。


4

精深的知识和编程专长意味着可以在所有抽象级别上自如。即

  • 库和API
  • 语言语义
  • 编译器优化
  • 编译器内部和代码生成
  • 运行时和垃圾收集器行为
  • 体系结构和指令集问题

我在过去15年中所看到的一切都表明,只有真正进入编译器和运行时,您才有机会变得精通。您可能不得不强迫自己采取步骤,并在堆栈中较低的下一个抽象层次上开始推理(和构建)软件,但这是获得专业知识的唯一方法。

我们所拥有的只是抽象语言。您必须了解如何设计和构建编程语言,才能真正了解机器在做什么。


3

阅读高级手册这不是特别深的知识。它在C#语言规范的 8.6.4节中发布。您应该养成至少略读所用语言的规范以及略过所有内置库的文档的习惯。

无论如何,这不是我对知识的深刻理解。这只是一个有趣的实现细节。如果设计人员解释了为什么以这种更加动态的方式完成操作,而不是仅仅检查对象是否实现Iterable,那么可能会更有趣。


1
我认为没有“掠过” C#语言规范这样的事情。
罗伯特·哈维

@RobertHarvey:您可以浏览大多数形式语言,涵盖您已经知道的内容,例如运算符优先级和声明语法,并专注于意外但有用的细节,例如C#foreach或Java枚举构造函数的确切行为。
凯文·克莱恩

您可以购买标准的带注释的版本。现在有点过时了,但是对于所覆盖语言的各个部分,注释仍然非常有趣。
约根·
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.