Roy Cheng
摘要: 你可以不写一行代码就把一个包含有多个Dll的C#程序合成为一个可独立运行的Exe文件。阅读全文
posted @ 2015-10-09 14:10 Roy Cheng 阅读(18612) 评论(22) 编辑
摘要: 还不会合并SVN分支?看看这篇文章吧。阅读全文
posted @ 2014-12-17 23:37 Roy Cheng 阅读(10057) 评论(0) 编辑
摘要: 弱引用是什么?要搞清楚什么是弱引用,我们需要先知道强引用是什么。强引用并不是什么深奥的概念,其实我们平时所使用的.Net引用就是强引用。例如:Cat kitty = new Cat();变量kitty就是一个强引用,它指向了堆中的一个Cat对象实例。我们都知道,CLR的垃圾回收机制会标记所有被强引用到的对象,而那些剩下的未被标记的对象则会被垃圾回收。换句话说,如果一个对象一直被某个强引用所指向,那么它是不会被垃圾回收的。从这一点来看,弱引用就完全不一样了——即使某个对象被弱引用所指向,该对象仍然会被垃圾回收。也就是说,弱引用不会影响对象的生命周期。System.WeakReference类是.阅读全文
posted @ 2013-12-21 09:10 Roy Cheng 阅读(5241) 评论(30) 编辑
摘要: 问:当我们new一个对象时,会发生什么事?答:调用该类型的构造函数。问题看似简单,不过事实上,CLR做的比这要多。。。要准确回答这个问题,还要分情况来说。new一个引用类型首先,要实例化一个引用类型,就一定需要在堆上分配内存。要分配内存,就需要先计算出这个引用类型占多大空间,需要给它分配多少内存。那怎么计算呢?简单!只要计算该类型所有字段的长度总和就可以啦。我们知道,引用类型的字段,占一个指针的长度(32位机器上是4个字节,64位机器上是8个字节)。值类型的字段长度可以通过递归的方法计算得出(递归终点是遇到引用类型或基本类型)。根据这些信息,我们就可以轻松计算出所有字段长度的总和了。但是实际上阅读全文
posted @ 2012-09-10 21:04 Roy Cheng 阅读(10211) 评论(11) 编辑
摘要: SortedList,SortedSet与SortedDictionary都是我们常用的泛型类型。当T是我们自定义的类型时,往往该类型的默认比较行为不是我们所期望的。例如,我们有如下很老土的Employee类: class Employee { publicint Id { get; set; } public String Name { get; set; } publicint Age { get; set; } }如果我们想让Employee类型按照Name字段升序排序,一般有两种做法。一种是让Employee实现IComparable或者ICo...阅读全文
posted @ 2011-07-21 08:03 Roy Cheng 阅读(2302) 评论(5) 编辑
摘要: 很多C#的教材都会强调对象相等的概念。我们都知道,在C#的世界里存在两种等同性。一种是逻辑等同性:如果两个对象在逻辑上代表同样的值,则称他们具有逻辑等同性。另一种是引用等同性:如果两个引用指向同一个对象实例,则称他们具有引用等同性。众所周知,Object类型有一个名为Equals的实例方法可以用来确定两个对象是否相等。Object的Equals的默认实现比较的是两个对象的引用等同性。而Object的派生类ValueTpye重写了Equals方法,它比较的是两个对象的逻辑等同性。也就是说,在C#里,引用类型的默认Equals版本关注的是引用等同性,而值类型关注的是逻辑等同性。当然,这并不总能满足阅读全文
posted @ 2011-06-08 09:23 Roy Cheng 阅读(5789) 评论(15) 编辑
摘要: 前一阵子我参加了一次笔试,其中有一道选择题让我印象深刻,是这样的:实例化一个X类型对象时所执行的顺序:A.调用X类型构造函数,调用X类型基类的构造函数,调用X类型内部字段的构造函数B.调用X类型内部字段的构造函数,调用X类型基类的构造函数,调用X类型构造函数C.调用X类型基类的构造函数,调用X类型构造函数,调用X类型内部字段的构造函数D.调用X类型基类的构造函数,调用X类型内部字段的构造函数,调用X类型构造函数我觉的这道题出得很没水平。在C++的世界里,我会毫不犹豫的选D。但是,由于C#引入了字段初始化器,所以选什么答案完全依赖于类具体是如何设计的。好吧,我们今天就来谈谈C#在类型实例化时都有阅读全文
posted @ 2011-05-27 07:37 Roy Cheng 阅读(6631) 评论(44) 编辑
摘要: 刚开始学习C#的时候,就听说CLR对于String类有一种特别的内存管理机制:有时候,明明声明了两个String类的对象,但是他们偏偏却指向同一个实例。如下:[代码]这里的same会被赋值为true。也就是说s1真的和s2引用了同一个String对象。当然,应该注意到的是s1和s2都被统一赋值为同一个字符串“Hello”,这才是出现上述情况的原因。现在我们初步得出结论,当有多个字符串变量包含了同样...阅读全文
posted @ 2011-05-24 23:23 Roy Cheng 阅读(12541) 评论(22) 编辑
摘要: 我们知道,在匿名方法或者lambda中,可以访问或者修改该匿的定义范围内的变量。例如:int num = 1; Func<int> incNum = () => ++num;其中lambda表达式使用了在其外部定义的变量num。我们可以认为该段lambda语句块构成了一个闭包,而这个闭包捕获了外部变量num。好了,不说那么多让人看着难受的定义套话了。我们进入正题,看看在C#中变量是如何被捕获的。来看一个例子: public Func<String> CreateFunction() { String str = "我的幸运数字是"; int n阅读全文
posted @ 2011-05-22 14:26 Roy Cheng 阅读(3040) 评论(6) 编辑
摘要: 在C#中,重载自增、自减操作符的语法并没有什么特殊之处,如下:public static SomeType operator ++(SomeType some){ //具体实现}对于C#中的自增、自减操作符重载,无论前缀式或是后缀式,都统统只需要一个实现。也就是说无论我是这样:someType++,还是这样:++someType使用SomeType类型的自增重载,上述代码中的实现都完全足够完成任务。但是,前缀式++与后缀式++的行为毕竟不同,为什么他们只需要一份同样的实现就可以达到我们需要的目的了呢?另外,重载操作符的第一原则就是不应该改变操作数对象,而应该返回一个新的对象。否则不仅很可能会令阅读全文
posted @ 2011-05-21 13:53 Roy Cheng 阅读(2390) 评论(8) 编辑