如何在不装箱的前提下调用“显式”实现的接口方法?(答案)

之前的问题是:假如一个struct实现了某个接口,却“显式”实现了其中的成员,那么我们又该如何访问这些成员?其实已经有不少同学抓住了关键,那就是使用泛型,例如有人提出了这样的辅助方法: static void Dispose<T>(T obj) where T : IDisposable { obj.Dispose(); } 我们没有进行类型转化,只是让运行时可以“认识到”类型T实现了IDisposable接口,这自然可以在不装箱的情况下调用其成员。可

如何在不装箱的前提下调用“显式实现”的接口方法?

上篇文章谈了针对一个struct对象使用using语句的时候是否会装箱的问题,结论是“不会”。尽管using语句是针对IDisposable接口的,但我们在调用的时候其实已经明确了目标方法,因此根本不需要装箱(或查找虚函数表)了。后来有同学在微博上提出,这点在《CLR via C#》这本书里提到过,于是我去翻了翻,原来是这样的: internal struct Point : IComparable { private readonly Int32 m_x, m_y

针对struct对象使用using关键字是否会引起装箱?

说起来这是个很简单的问题,我以前肯定可以给出确切地答复,但是前几天想到这点的时候突然楞住了。把这个问题发到微博上去之后,很多人说是“会”,但要么是猜的,或是给出的原因明显不靠谱。最后我只能自己简单研究一下了,最后得到的结果是“不会”装箱。请注意,这个问题是指,对于一个实现了IDisposable接口的值类型对象使用using语句,而不是将它直接复制给一个IDisposable引用——后者显然是会装箱的,会对性能产生一定负面影响。 首先我们来写一小段测试代码: intern

串与绳(1):.NET与Java里的String类型

话说“字符串”是我们平时最常用的数据类型之一,它表示一个字符序列。在大部分的语言中,字符串还是一个不可变(Immutable)的数据类型。“不可变”意味着要改变则只能生成新的字符串,无论是连接两个字符串,获取或是替换字符串的一部分,这对于内存和CPU都是不可避免的开销。在一般情况下,只要使用合理这些开销都不会构成大问题。不过对于某些类型的应用,例如我前段时间在工作中涉及到的编辑器(IDE那种),就会带来较多麻烦,于是便用到了一个名为Rope的数据结构。Rope其实是一种很简单

Everpage:将Evernote的笔记展现在页面上

我这人尤其强调阅读体验,无论是作为文章的读者还是作者。假如遇到一篇格式糟糕的文章,我会完全没有耐心读完它。我对于阅读工具的展现格式也是各种挑剔,例如字不能太小,内容不能太宽或太窄,段落间距必须大过行间距等等,例如OS X上著名的RSS阅读器Reeder无法自定义样式,我甚至钻进其App内部修改其CSS文件。Evernote也是一样,无论是其网页版还是客户端,其阅读体验在我看来都比较糟糕,于是我在愤而花了差不多半天的时间打造了Everpage这个小玩意儿。简单来说,就是把一篇E

真是O(1)吗?想清楚了没?

当然标题里这个O(1)可以换成任何复杂度。 话说写程序的时候我们会用到各种数据结构,但十有八九不会由我们自己从头写起,都会直接拿来用。于是很多人就会记住,譬如HashMap或Dictionary的存取是O(1)的操作,二分查找什么的则是O(log(N))。不过,我们在实践中直接把这些类拿来用的时候,最好也留个心眼,知道这些类内部到底做了些什么,为什么它们能够达到O(1)之类的时间复杂度。 例如,我们都知道List<T>的Add是O(1)的操作,但之所以它是O(

一个最基本的HashedLinkedList

Tmc的初衷是补充一些常用的数据结构,例如对null作为字典键的支持,以及带有一个额外Remove方法的HashDictionary。但是,其实我创建Tmc项目的“初衷”却是HashedLinkedList。.NET BCL中已经有一个LinkedList,这是一个双向链表。说起来,我之前在面试中经常会提出一系列数据结构的基础问题,其中便包含LinkedList,我会问各个操作的时间复杂度,以及如何改进它们。例如,如何将它的Remove操作优化成O(1)的时间复杂度?最容易想

阅读.NET源代码那些事

谁都知道.NET(的大部分组件)是不开源的,但是我不止在一个场合不止一次地强调过,“不开源”不代表你没法看代码,不代表你没法知道里面发生了什么。这里我不是在说.NET Reflector或是ILSpy这类反编译工具,当然它们在平时开发中也起到了很大的作用,不过很多时候更直接的方式便是阅读代码本身,尤其是当你像我一样时不时要“抄”点代码的时候。由于最近我在Tmc中“大张旗鼓”地使用.NET中BCL的代码,因此也再次强调一下这部分经验。 在.NET最初的几年里,要从框架内部抄写

NullableKey:解决Dictionary中键不能为null的问题

众所周知,.NET中Dictionary的键不能为null,否则会抛出NullReferenceException,这在某些时候会显的很麻烦。与此相对的是Java中的HashMap支持以null为键,则方便许多。尽管null的确不是个好东西,但它既然已经存在,既然给我们造成了麻烦,我们就要想办法去解决它。实现一个自己的字典类自然可行,但要精心实现一个高效的字典并不是件容易的事情,例如BCL中的Dictionary.cs就有超过2000行代码。此外另一个容易想到的方法便是实现I

不同泛型参数区分的独立类型

相对于的Java的“类型擦除(Type Erasure)”来说,.NET中的泛型可谓是真正的泛型,这让我们可以有能力区分运行时所使用的不同的具体类型,大大增强了程序设计的性能和表现能力。 打个比方,在Java 8中终于引入了Lambda表达式,但是由于它的伪泛型只能是一个“引用类型”而不能是“基础类型”,因此我们没法从int数组发起函数式操作,最后也没法回到List<char>这种类型(事实上这种类型在Java中根本不存在)。这除了影响编程体验和表达能力以外,对