[藏]图文并茂详解Eclipse断点

本文转自:http://my.oschina.net/colorleaf/blog/176569 这个算说的比较清楚的了,虽然简单但是很有用。收藏一下。 详解Eclipse断点 大家肯定都用过Eclipse的调试的功能,在调试的过程中自然也无法避免要使用断点(breakpoint),但不知是否对Eclipse中各类断点都有所了解。本篇图文并茂地介绍了Eclipse中全部类型的断点,及其设置,希望对大家有所帮助。(2011.11.20) 1. 示例程序 BreakpointDemo是一个臆造的应用程序,只是为了便于讲解Eclipse中各类断点的使用罢了。其代码如下图所示, BreakpointDemo主要包含两个方法: [1]setValue,该方法根据指定的次数(count),对成员变量value进行赋值,值的范围为0-9的随机整数。 [2]printValue,该方法会调用setValue()对value进行赋值,并打印出value的值;但,如果value能被3整除,那么就会抛出IllegalArgumentException异常。 2. Line Breakpoint Line Breakpoin是最简单的Eclipse断点,只要双击某行代码对应的左侧栏,就对该行设置上断点。此处,对第20行代码设置上Line Breakpoint,如下图所示, 可以为Line Breakpoint设置一个条件,那么当程序运行到该断点时,只有满足设定的条件,才会被中断。右键点击第20行的断点,选择"Breakpoint Properties…" 在弹出的属性对话框中,勾选上"Conditional",然后在文本框中输入"count % 2 == 0"。 该条件表示,当程序运行到第20行时,只有当count为偶数时,程序才会被中断。细心地话,你会发现该断点的图标发生了改变,多了一个问号。 3. Watchpoint Line Breakpoint关注于程序运行的"过程",大家也常把使用这种断点的调试称为单步调试。但有时候,我们对程序的运行过程不太了解,可能也不太关心,不能确定在什么地方设置断点比较合适,而可能比较关注某个关键变量的变化或使用。此时,就可以为该变量设置一种特殊的断点–Watchpoint。在此示例,我们最关心的就是成员变量value的值,那么就可以为它设置一个Watchpoint,双击第9行代码对应的左侧栏就可以了。 使用在2中所提及的方法,查看该断点的属性, 默认地,当该变量被访问或它的值被修改时,程序都会被中断。但在本示例中,只希望当对value的值进行修改时程序才需要被中断,所以取消对"Access"的勾选。 这时,我们会发现原来的Watchpoin图标也有变化了。 4. Method Breakpoint 与关注对某个变量的访问与修改一样,我们也可以关注程序对某个方法的调用情况,即,可以设置Method Breakpoint。在此处,设置针对方法setValue的Method Breakpoint。同理,双击第11行代码对应的左侧栏即可。 仍然要查看该断点的属性。默认地,只勾选了"Entry",而没有勾选"Exit"。 这表示,当刚进入该方法(调用开始)时,程序会被中断;而,离开该方法(调用结束)时,程序并不会被中断。在本示例中,需要同时勾选上"Exit"。 点击OK之后,可以看到该断点的图标也有所改变。 根据这里的设置,当程序运行到第20行后会在第12行被中断,尽管这里没有显式的断点,但这就是setValue()方法的入口(Entry)。必须注意地是,程序在运行到第16行时不会被中断,尽管它看起来像是setValue()方法的出口(Exit)。实际上,程序会在第17行被中断,这里才是setValue()调用结束的地方。 5. Exception Breakpoint 如果,我们期望某个特定异常发生时程序能够被中断,以方便查看当时程序所处的状态。通过设置Exception Breakpoint就能达到这一目标。本示例故意在第23行抛出了IllegalArgumentException异常,我们期望程序运行到此处时会被中断。但我们不直接为此行代码设置Line Breakpoint,而是为IllegalArgumentException设置Exception Breakpoint。设置Exception Breakpoint的方法与其它类型断点都不同,它不能通过双击左侧栏的方式在代码编辑器上直接进行设置。点击Breakpoints视图右上角形如Ji的图标, 会弹出如下所示的对话框, 在其中选中IllegalArgumentException,并点击OK,这时一个Exception Breakpoint就设置好了。 当value为3的倍数时,程序会在第23行被中断,这时我们就能使用调试器来看看value具体是等于0,3或6。 **6\. Class Load Breakpoint** 还有一种大家平时可能不太用的断点--Class Load Breakpoint,即当某个类被加载时,通过该断点可以中断程序。 [![15153248_2UA6](/images/8158c897f4e784042063a484c7256901902b6c20.png)](http://leaverimage.b0.upaiyun.com/2013/11/15153248_2UA6.png) 小结 上述的Eclipse断点,我们在现实工作中肯定都有意或无意地使用过其中的几种,只是不一定十分了解内情罢了。使用好Eclipse的各种断点,可以把很好地帮助我们分析程序,定位问题。

2013-11-16 · 1 min · bystander

Maven实例入门-随机数生成

看了很多个例子,发现这个最好,译文中会带有我的一些了理解,有问题欢迎指出。 0.Maven是什么? Apache Maven,是一个软件(特别是Java软件)项目管理及自动构建工具,由Apache软件基金会所提供。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。 可以看到,核心就是项目管理和自动构建了,从例子中将会体会更深。本例创建一个随机数生成程序。 1.从Maven模板创建项目 Maven的环境变量配置和java类似,直接添加系统变量MAVEN_HOME指向你下载的maven目录,然后将bin目录添加到path环境变量里。 在命令行下,进入到你想存储项目的位置,比如,我自己有个叫work的目录,那么我就cd到work目录,然后按下面的格式输入命令 mvn archetype:generate -DgroupId={project-packaging} -DartifactId={project-name} -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false 这是告诉Maven从**maven-archetype-quickstart **创建一个java项目,如果你这个参数不填,那么会列出一个列表,让你选择你想创建什么类型,比如web项目啊,啥的。 友情提示:是不是太难记了..好吧,直接输入 mvn archetype:generate 根据向导来创建把。。 比如 >mvn archetype:generate -DgroupId=com.mkyong -DartifactId=NumberGenerator -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false [INFO] Scanning for projects... [INFO] [INFO] -- omitted for readability [INFO] ---------------------------------------------------------------------------- [INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0 [INFO] ---------------------------------------------------------------------------- [INFO] Parameter: groupId, Value: com.mkyong [INFO] Parameter: packageName, Value: com.mkyong [INFO] Parameter: package, Value: com.mkyong [INFO] Parameter: artifactId, Value: NumberGenerator [INFO] Parameter: basedir, Value: /Users/mkyong/Documents/workspace [INFO] Parameter: version, Value: 1.0-SNAPSHOT [INFO] project created from Old (1.x) Archetype in dir: /Users/mkyong/Documents/workspace/NumberGenerator [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.917s [INFO] Finished at: Mon Dec 17 18:53:58 MYT 2012 [INFO] Final Memory: 9M/24M [INFO] ------------------------------------------------------------------------ 这里的groupId就是包名,artifactId就是类名,以后具体的一些其他参数我希望有时间可以跟大家分享。 2.Maven目录结构 上面的命令第一次执行的时候会从apache网站下载maven的一些其他东西,所以务必保持联网。执行成功后,会生成一个这样的目录结构 NumberGenerator |-src |---main |-----java |-------com |---------mkyong |-----------App.java |---test |-----java |-------com |---------mkyong |-----------AppTest.java |-pom.xml 这里main目录是我们的程序住代码目录。源代码会放在/src/main/java/包名 目录里,而单元测试代码会放在/src/test/java/包名 目录里。当然还有一个标准的pom.xml文件会生成。这个pom文件其实类似于Ant的build.xml文件,它包含了项目的信息,从目录结构到项目插件到项目依赖,都有了。。 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mkyong</groupId> <artifactId>NumberGenerator</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>NumberGenerator</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project> 3.用Eclipse写代码 maven已经生成了一个完整的工程了,为了能够导入到eclipse里来编辑代码,我们可以把这个项目转换成eclipse可用的。 ...

2013-09-19 · 2 min · bystander

《软件测试》一点笔记

这两天在读《软件测试》,书不厚,也就300页,有些观念还是挺诧异的,比如软件功能超出产品说明书也算作软件缺陷…想想也能明白,只是猛然看到还是很惊异..简单记录一下读书过程中一些重要的笔记.留作备份. 软件缺陷: 1.软件为达到产品说明书表明的功能 2.软件出现了产品说明书指明不会出现的错误. 3.软件功能超出产品说明书指明范围 4.软件未达到产品说明书虽未指出但应达到的目标 5.软件测试员认为软件难以理解,不易使用,运行速度缓慢,或者最终用户认为不好. 为什么会出现软件缺陷 最大的原因是产品说明书.而并非编程错误,第二大来源是设计方案 软件测试员的目标是发现软件缺陷,进可能早一些,确保其得到修复 完全测试程序是不可能的 不要总是报告坏消息,如果软件没有错误,就夸他们,和他们聊天 可靠性只是质量的一个方面,可能还包括功能齐全,技术制裁,包括色彩等 在设计和执行测试案例时,首先进行通过测试,在破坏性试验之前看看软件基本功能是否实现是很重要的,否则在正常使用软件时就会奇怪为什么有这么多软件缺陷 软件测试员必须测试程序的状态及其转换 动态白盒测试的目标是寻找软件缺陷,调试则是为了修复他们 静态黑盒子(审查设计说明书),动态黑盒子,静态白盒子,动态白盒子 进行白盒测试前,一定要根据说明书建立黑盒测试案例 语句覆盖是程序的所有语句执行,分支覆盖则是所有分支都被执行,条件覆盖则要保证IF语句的每一种可能性都被覆盖 优秀UI的七个要素: 1.符合标准和规范,2.灵活性,3.正确性。4.直观性。5.舒适性,6.实用性。7.一致性 测试存根用于自顶向下的测试,清查到低级模块或者把自己替换为低级模块,主要测试高级模块,外表和行为就像是低级模块

2013-07-26 · 1 min · bystander

一道笔试指针题目详解

看到本题是在搜狗某年的笔试题上,看也没人给出非常详细的讲解,直接给出了答案,我来尝试写一写, 貌似本题来源自<**The C Puzzle Book> ,**搜狗也只是换了一下字符串,直接看题吧 #include <stdio.h> char *c[]={"ENTNG", "NST","AMAZI","FIRBE"}; char** cp[]={c+3, c+2, c+1, c}; char ***cpp= cp; int main() { printf("%s",**++cpp); printf("%s ",*--*++cpp+3); printf("%s",*cpp[-2]+3); printf("%s",cpp[-1][-1]+1); } <span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">请写出程序的执行结果....</span> 首先从左到右看: char *c[]= { "ENTNG", "NST", "AMAZI", "FIRBE" }; *c[] 是一个字符,因此,c[]是指向该字符,c就是一个数组(数组的内容为指向字符的指针),c已经被初始化了. char** cp[]={c+3, c+2, c+1, c}; 再看第二行,**cp[]是一个字符,*cp[]就是一个指针,指向该字符,cp[]就是一个指针,指向该指针,而cp就成为了指针数组,内容是指向字符的指针的指针。并且通过c的元素进行了初始化 char ***cpp= cp; 第三行,***cpp是一个字符,**cpp指向该字符,*cpp指向该指针,cpp就指向该字符的指针的指针. 然后我画一张图表示初始的情况看看 然后对于下面的输出语句,通过操作符优先级使用括号来区分一下: *(*(++cpp)); 这个嘛,就是把cpp后移(注意cpp已经改变了)然后就指向了cp[1],然后两次取其值即可得到AMAZI 推导过程如下: ++cpp -> cp[1] // cp[1] -> c+2 ++cpp = &cp[1] // &(c+2) *++cpp = *(&c+2) // c[2] **++cpp = *&c[2] 然后看第二个 (*(--(*(++cpp))))+3; 加括号后如上,cpp再加一,就指向了cp[2],取一次值(也就是*号)就变成了c[1],然后--c[1]就指向了c[0],取值就成了c[0]的地址,然后地址+3,就是NG了 (*(cpp[-2]))+3; 上面,cpp指向cp[2]了,然后呢,cpp[-2] 相当于*(cpp-2),间接引用cp[2],这样cpp[-2]就指向了cp[0]了,然后,就是FIRBE了,加3就是BE了 最后 (cpp[-1][-1])+1; cpp还是之前的cp[2],cpp[-1][-1]相当于*(*(cpp-1)-1),先减1指向了cp[1],取一次值就是c[2]了,然后c[2]-1就成为c[1]了,然后+1之后就是ST了. 所以,最后输出就是 AMAZINGBEST 错误之处还望指正.

2013-04-17 · 1 min · bystander

C#中的Debug类

位于命名空间System.Diagnostics中 1.Debug.Print方法 Debug.Print("Today: {0}", DateTime.Today); 2.Debug.WriteLine方法 Debug.WriteLine("Have a nice day"); 3.TraceListener类 DelimitedListTraceListener创建的时候指定一个文件名,当Flush调用的时候,就被覆写到文件里。 TraceListener listener = new DelimitedListTraceListener(@"C:\debugfile.txt"); // Add listener. Debug.Listeners.Add(listener); // Write and flush. Debug.WriteLine("Welcome"); Debug.Flush(); 4.Debug.Write和WriteIf以及WriteLineIf方法 Debug.WriteLineIf(IsThursday(), "Thursday"); 第一个参数一个bool值,为真则输出。 5.Debug.Assert方法 Debug.Assert(value != -1, "Value must never be -1."); 如果表达式为false,则输出。

2013-03-01 · 1 min · bystander

现代操作系统的调度

这几天在读《现代操作系统》,想起当时学这门课的时候,并没有感觉那么爽,现在通读这本书,知识的过渡性和结构性令我叹服。感受操作系统的魅力吧。 批处理系统中的调度: 1.先来先服务 2.最短作业优先 只有在所有的作业都可以同时运行(也即同时到达)的情况下,最短作业优先算法才是最优化的。 3.最短剩余时间优先-最短作业优先的抢占式版本。调度算法总是选择剩余时间最短的那个进程运行,注意,运行时间必须提前掌握,当一个新的作业到达时,其整个时间同当前进程的剩余时间做比较,如果更少。就运行新进程。可以使新的短作业获得良好的服务。 交互式系统的调度 1.轮转调度。 最古老,最简单,最公平切使用最广,每个进程被分配一个时间片。如果进程在时间片结束之前阻塞或结束,则CPU立即切换。调度程序只是维护一张可运行进程列表,当进程用完它的时间片后,就被移到队列的末尾。时间片太短会导致进程切换过多,降低CPU效率,设置的太长又引起对短的交互请求的响应时间变长。通常20-50ms算合理。 2.优先级调度 为了防止高优先级进程无休止的运行下去,可以在一个时钟中断里降低当前进程的优先级,如果这导致该进程的优先级低于次高优先级的进程,则切换或者也可以赋予每个进程一个时间片。可以和轮转调度一起工作,设置每个优先级上有多个进程。优先运行高优先级,并未高优先级上的进程按照轮转换着运行,如果高优先级没了。就进入到较低优先级。。。问题是如果不偶尔对优先级进行调整,则可能发生饥饿现象。 3.多级队列 CTSS的设计者发现为CPU密集型进程设置较长的时间片比频繁的分给他们很短的时间片更为高效(减少了交换次数),但长时间的进程又会影响响应时间,方法是设立优先级类,最高优先级类里的进程运行1个时间片。次高运行2个。以此类推。当一个进程用完分配的时间片后,被移动到下一类。大致算法都是用于讨好交互用户和进程,而不惜牺牲后台进程 //故事:可以采用只要终端上有Enter键按下,就将该终端上的进程移到最高优先级类。假设当前进程急需交互,但是。一个人发现了。大家都开始用。。。理论和实际差异太大。。哈哈 4.最短进程优先 这个很好立即,但难点在于如何找出最短的那个。一种方法是根据过去的行为推测。假设每个命令执行时间为T0,下一次运行时间为T1,则可以根据aT0+(1-a)T1来估计时间。。a被用来决定尽快忘掉老的运行时间还是记住它。这种算法成为老化算法。通常选a=1/2 5.保证调度 就是保证每个用户获得cpu的1/n,系统需要跟踪进程的cpu时间,他实际获得如果多于应该获得的。则转向实际获得小于应该获得的。 6.彩票调度 保证调度很难实现,而彩票调度算法是向进程提供各种系统资源的彩票。一旦需要做出一项调度决策时,就随机抽出一张彩票。谁获得谁就上。比如视频服务器,可以为不同的帧速率提供不同的彩票。然后分配cpu 7.公平分享调度 这个就考虑到了进程的所有者。需要我们定义公平的含义。是保证每个用户只占用的时间相等还是其他了。 实时系统的调度: 可以分为硬实时和软实时,前者必须满足绝对的截止时间,后者则可以容忍一些。用户级线程系统是不知道的。用户级和内核级的差异主要在性能,用户级需少量的机器指令,而内核级需要很多的。过程。采用轮转和优先级调度更常见一些。 //操作系统的大神们太强大了。哲学家进餐问题居然可以通过拿起左边叉子以后,检测右边是否可用,如果不可用,则等待一个随机的时间。这种方案是可行的。在极少的情况下不可用。。

2013-01-24 · 1 min · bystander

社工字典生成工具

在家无聊写了这个工具,主要是为了防止自己这一直写随笔把本行忘了。。也熟悉一下代码。。暂时不放源代码了。以后改的好一点再发吧。 作者:bystander 博客:http://leaver.me 转载请注明出处! 涉及到的东西有: 1.C#隐藏TabControl的header部分,前面的文章有介绍 2.获取窗体全部的某一类控件(这个无聊的话抽象出一个通用的方法出来,以后就可以直接用了) /// <summary> /// 获取所有的文本框控件 /// </summary> /// <param name="control"></param> /// <returns></returns> private List<TextBox> GetAllControls(Control control) { foreach (Control con in control.Controls) { if (con.Controls.Count > 0) { GetAllControls(con); } else if (con is TextBox) { tBoxList.Add(con as TextBox); } } return tBoxList; } 3.文件操作 4.字符串操作 反正很简单,主要就是写的时候思路要清晰。知道大部分使用密码的规则。处理一下生日格式。否则后面很麻烦。。相应的验证也比较少。界面依然毫无美感。。 总结: 现在发现在控件命名上越来越顺利了。自我感觉良好。后面慢慢的要开始尝试使用学到的一些新的技术点。。 下载:社工字典生成工具

2013-01-21 · 1 min · bystander

Lambda高手之路第四部分

首先祝大家平安夜快乐。本篇介绍一些流行的JavaScript模式。为下一篇打基础 使用/了解JavaScript的一个好处就是函数的高级用法。。在JavaScript里。函数仅仅是对象。他们可以有赋给他们的属性。而在C#中。我们不能做我们可以在JavaScript的全部事情。但是我们仍然可以做些事情。一个原因是JavaScript在函数里给变量以作用域。因此,不得不通过创建函数,大多数情况是匿名的来定位变量。而在C#中。通过使用块,通过花括号来创建作用域 当然,换种方式来说。C#中,函数也会给变量作用域。通过使用Lambda表达式。我们通过花括号在其里面创建了一个变量。然而。我们也可以局部的创建作用域。 我们来看看通过使用Lambda表达式可以实现一些在JavaScript里面有用的模式把。 回调模式 这个模式是个老的模式。事实上。回调模式从.net 的第一版就开始使用了。但是是以一种很简单的方式实现的。而现在。通过使用Lambda表达式。闭包,捕获变量等特性能够允许我们写出如下的代码来。 void CreateTextBox() { var tb = new TextBox(); tb.IsReadOnly = true; tb.Text = "Please wait ..."; DoSomeStuff(() => { tb.Text = string.Empty; tb.IsReadOnly = false; }); } void DoSomeStuff(Action callback) { // Do some stuff - asynchronous would be helpful ... callback(); } 对于JavaScript程序员会觉得这没什么啊。他们使用这个模式太多了。然而,它非常有用。因为我们可以使用参数作为Ajax相关事件的事件处理器(比如oncompleted,onsuccess),等等。如果你使用LINQ,那么你可能也会用到回调模式的一些东西。举个例子。LINQ的where子句将会在每一次迭代中回调你的查询语句。这只是回调函数的一个例子。在.net的世界里。事件如它名字所暗示的那样。通常是事件处理的首选方法。这有时候很像一个回调。他有两个参数。有一个特殊的关键字和一个类型模式(两个参数分别是sender和arguments,sender通常是object类型。Arguments通常继承自EventArgs) 可以通过+= 和-=给事件添加/删除事件处理程序。 返回方法 和普通的方法比较。Lambda表达式也可以返回一个方法指针(就是一个委托实例),这意味着我们可以使用Lambda表达式创建/返回一个lambda表达式(或者今年仅是一个已定义好的方法的委托实例),大量的情况下。这个模式也很有用。首先看一下例子。 Func<string, string> SayMyName(string language) { switch(language.ToLower()) { case "fr": return name => { return "Je m'appelle " + name + "."; }; case "de": return name => { return "Mein Name ist " + name + "."; }; default: return name => { return "My name is " + name + "."; }; } } void Main() { var lang = "de"; //Get language - e.g. by current OS settings var smn = SayMyName(lang); var name = Console.ReadLine(); var sentence = smn(name); Console.WriteLine(sentence); } 代码本应该更短些。我们可以让default如果请求的语言没有找到。只是抛出一个异常即可。不过。这个例子展示了这是一种方法工厂。另一种同等效果的方法是包含一个Hashtable。或者更好的话用Dictionary<K, V> ...

2012-12-24 · 3 min · bystander

Lambda高手之路第一部分

好长时间没发技术文章了,恰好看到一篇非常详细的Lambda文章。一边翻译一边学习。题目好像有点霸气。。 介绍 Lambda表达式是使代码更加动态,易于扩展并且更加快速(看完本文你就知道原因了)的强有力的工具。也可以用来降低潜在的错误。同时可以利用静态输入和智能提示,就像VS里一样。 Lambda表达式在.net framework 3.5中提出来。并且在LINQ和ASP.NET MVC内部的一些技术中扮演了相当重要的角色。如果你考虑一下ASP.NET MVC中各类控件的实现。你就发现。奥妙就是他们大多使用了Lambda表达式。和Lambda表达式一起,使用Html扩展方法将会使得在后台创建模型成为可能。 本文会讲到如下的知识。 1.简短的介绍-Lambda表达式是什么,以及为什么和匿名方法不同(之前我们使用的) 2.走近Lambda表达式的性能-在哪些情况下比起标准方法,Lambda会提高/损失性能 3.深入-Lambda表达式在MSIL代码中是什么样 4.一些来自JS世界的模式映射到C#中 5.那些能够提高性能,并且代码看起来相当舒服的使用Lambda的情况。 6.一些我提出的新模式-当然有可能别人也提出来了。但这是我的思考结果。 如果你期望本文是一篇入门教程我可能要让你失望了,除非你真的很优秀并且很聪明,当然我不是这种人,所以我也想提前声明一下:为了读懂这篇文章你可能需要C#的一些高级知识,并且对C#比较了解。 你应该期望本文试着解释一些事情给你,也会解释一些有趣的问题,至少对我来说是这样的。最后我会展示一些实际的例子和模式,如我所说,Lambda表达式简化了很多情况。因此写显式的模式很有用。 背景知识-什么是Lambda表达式 在C#1.0中,委托被提出了,它使得传递函数成为可能,一句话就是委托就是强类型的函数指针,但委托比指针更强大。一般传递一个函数需要如下几步。 1. 写一个委托(就像一个类)包含返回类型和参数类型 2. 使用委托作为某一个函数的参数类型,这样,该函数就可以接受和委托描述的有着相同签名的函数了 3. 将一个委托类型的函数传递给委托,创建一个委托实例。 如果听起来很复杂,确实本来很复杂,但这是必需的。(虽然不是造火箭,但是比你认为的要更多的代码),然而步骤三不是必需的,编译器会为你做他,但是步骤1和2却是必不可少的。 幸运的是C#2.0出现了泛型,现在我们也可以写泛型类,方法,更重要的是,泛型委托,然而,直到.net framework 3.5的时候。微软意识到实际上只有两种泛型委托(当然有一些不同的重载),会覆盖99%的使用情况: 1.Action 没有任何输入参数,也没有输出参数。 2.Action<t1,…t16> 需要1-16个参数,没有输出参数。 3.Func<t1….t16,tout>需要0-16个参数,一个输出参数 Action和其对应的泛型版本(仅仅是一个动作,执行一些事情)返回void的时候。Func则可以返回最后一个参数指定的类型,通过这两个委托类型,我们事实上,大部分情况下。前面提到的三步中的第一部就不用写的。而第二步仍然需要。 那么如果我们想要运行代码的时候怎么做呢。在C#2.0中问题已经可以解决了。在这个版本里。我们可以创建委托方法,也就是一个匿名方法,然后这个语法一直未能流行起来,一个相当简化的匿名方法的版本类似这样: Func<double, double> square = delegate (double x) { return x * x; } 为了提高这种语法,欢迎来到Lambda表达式的国度。首先,这个Lambda名字怎么来的?事实上。来自于数学上的λ演算,更准确的说他是数学中一个正式的系统。用于通过变量绑定和替换来进行表达式计算,所以我们有0-N个输入参数和一个返回值,而在编程中,也可以没有返回值 我们看一下Lambda表达式的一些例子 //编译器可以识别,然后就可以通过dummyLambda();来调用了 var dummyLambda = () => { Console.WriteLine("Hallo World from a Lambda expression!"); }; //可以通过类似 double y = square(25);来使用 Func<double, double> square = x => x * x; //可以通过类似double z = product(9, 5);来使用 Func<double, double,double> product = (x, y) => x * y; //可以通过类似printProduct(9, 5);来使用 Action<double, double> printProduct = (x, y) => { Console.Writeline(x * y); }; //可以通过类似var sum = dotProduct(new double[] { 1, 2, 3 }, new double[] { 4, 5, 6 }); Func<double[], double[], double> dotProduct = (x, y) => { var dim = Math.Min(x.Length, y.Length); var sum = 0.0; for(var i = 0; i != dim; i++) sum += x[i] + y[i]; return sum; }; //可以通过类似 var result = matrixVectorProductAsync(...);使用 Func<double[,], double[], double[]=""> matrixVectorProductAsync = async (x, y) => { var sum = 0.0; /* do some stuff ... */ return sum; }; 从上面的代码段里我们可以学到一些东西 ...

2012-12-18 · 2 min · bystander

C#与.net 程序员面试笔记

这是前几天读的书。书不难。10-13章跳过了。以后再看。 以前,一个应用程序对应一个进程。并且为该进程指定虚拟内存,这样。进程会消耗很多资源,而且进程之间的通信业比较麻烦 应用程序域可以理解为很多应用程序域都可以运行在同一个.net 进程中,降低内存消耗。同时不同的域之间隔离。安全有保证。通信也简单。 程序集是指包含编译好的。面向.net framework的代码的逻辑单元。是完全自我描述性的一个逻辑单元。可以存储在多个文件中。简单来说,程序集就是几个彼此有关联程序文件的集合。程序集会包含程序的元数据。描述了对应代码中定义的方法和类型。 装箱和拆箱:装箱转换是将一个值类型显式或隐式的转换成一个object对象。并且把这个对象转换成一个被该值类型应用的的接口类型。装箱后的object对象中的数据位于堆中。一般应该避免这种运算。 CLR将值类型的数据包裹到匿名的托管对象中,并将托管对象的引用放在Object类型的变量中。这个过程称为装箱。一般还是使用泛型来代替多好。 值类型和引用类型:值类型实例通常分配在线程的栈上。并且不包含指向任何实例数据的指针。引用类型实例分配在托管堆上。变量保存了实例数据的内存引用。引用类型复制的话会导致引用同一个内存地址。 C#预处理指令是在编译时调用的。预处理指令通知C#编译器要编译哪些代码。并指出如何处理特定的错误和异常。比如用在一些调试的时候。在顶部define一个debug 内部的测试部分写上测试用例。具体示例 //定义条件变量,注意条件变量的定义要在代码的最前面 #define Debug using System; namespace MyConsole { class Preprocesor { public static void Main() { //如果条件变量是Debug则运行单元调试代码,再运行功能模块返回运行结果 #if Debug Console.WriteLine("运行单元测试模块"); Console.WriteLine("运行功能模块,返回输出结果"); Console.Read(); #elif Release //如果条件变量是Release,则直接运行功能模块返回运行结果 Console.WriteLine("运行功能模块,返回输出结果"); Console.Read(); #endif } } } C#中的指针 指针是一个无符号整数。是以当前系统寻址范围为取值范围的整数,CLR支持三种指针类型:受托管指针,非托管指针,非托管函数指针,受托管指针存储在堆上的托管块的引用,一个非托管指针就是传统意义上的指针,要放在unsafe中使用,C#中指针并不继承自Object String 是CLR的类型名称。而string是C#的关键字。其实C#编译时。。会增下如下代码: using string=System.String Array 到ArrayList的转换 1.使用ArrayList.Adapter(ArrayName) 可以直接得到ArrayList 2.使用遍历逐个添加到ArrayList里。 反向的话直接使用(Array[])ArrayListName.ToArray(typeof(Array));即可 checked和unchecked语句用于控制整形算术运算和显示转换的溢出检查上下文。checked关键字用于对整型算术运算和转换显式启用溢出检查。因为默认情况下。如果表达式产生的值超过了类型的范围。则常数表达式将会导致编译时错误。而非常数表达式则在运行时计算并将引发异常。 Asp.Net 中的Request对象主要功能是从客户端得到数据信息。他的属性比较多。比如UserLanguage,TotalBytes,Path,ApplicationPath ViewState是其的一个重要特性。用于把生成页面要用的状态值保存到一个隐藏域里。而不是用cookie/内存 SOAP是Web Service应用的基础协议。他是一种轻量的简单的。基于xml的协议。被设计成在wEb上交换结构化的和固有的信息。 WSDL是一种用于描述web服务和说明如何与Web服务通信的XML语言。WSDL是一种符合XML语法规范的语言。它的设计完全基于Soap协议的实现。当一个WEb Service 服务器期望为使用者提供服务说明时,WSDL语言是最好的选择之一。 **对企业的一些认识 ** 千万不要说自己未来的打算是做到管理层,首先对管理层的定义不清楚。职务不清楚。所以保险的答案是我会努力钻研技术。使得能够达到业内的专业人士。深刻理解公司和行业 我是为了找一份长期性的工作。我不喜欢频繁的跳槽我希望在这个利于发展自己的事业。深入学习。向专业人士请教。那。该我想问这个职务是长期的吗? 不要把公司想像成慈善机构。工作的运作方面应该是尽可能快的实现盈利。树立品牌,赢得客户。我的工作就是完成企业的良性运作。 如果被问到是否需要考虑看分数。应该说用人单位确实需要全面考量。也要考虑应聘者的工作积极性/服从性。实际经验/对开发的理解诶。这些也许比分数更有价值。 应届生的优缺点应该是足够的理论知识和专业能力。缺点是工作和社会经验不足。

2012-11-28 · 1 min · bystander