同学发过来一道有意思的题

For a given chemical formula represented by a string, count the number of atoms of each element contained in the molecule and return an object (associative array in PHP, Dictionary<string, int> in C#, Map<String,Integer> in Java).

For example:

var water = 'H2O';
parseMolecule(water); // return {H: 2, O: 1}

var magnesiumHydroxide = 'Mg(OH)2';
parseMolecule(magnesiumHydroxide); // return {Mg: 1, O: 2, H: 2}

var fremySalt = 'K4[ON(SO3)2]2';
parseMolecule(fremySalt); // return {K: 4, O: 14, N: 2, S: 4}

As you can see, some formulas have brackets in them. The index outside the brackets tells you that you have to multiply count of each atom inside the bracket on this index. For example, in Fe(NO3)2 you have one iron atom, two nitrogen atoms and six oxygen atoms.

阅读全文

日常新需求

新的需求又来了。这次是程序在编译后6个月拒绝启动。BETA性质的软件都有类似的需求。但大部分软件要么是启动时检查更新,要么是联网判断是否过期。对于我们现在做的这个小工具太小题大做了。根据编译时间判断过期的需求看似奇葩,也是有点道理的。

阅读全文

值类型与引用类型

C#中的类型分为引用类型和值类型。使用struct或enum关键字修饰的类型定义是值类型,使用class或delegate关键字修饰的类型是引用类型。引用类型和值类型各有限制,分别适用于不同的场景。不同于C++,C#中的值类型只能分配在栈上*1,引用类型只能分配在GC堆上。C#中的GC是精确式GC,这就对GC堆上的指针有了一些要求。这是引用类型有开销的原因之一。

Sync block index 与 Type object pointer

读过C# vir CLR的同学会知道,引用类型的开销是Sync blockindex和Type object pointer。他们的长度是都是一个字长。即在32位CLR上是4字节,在64位CLR上是8字节。Sync block index在CLR中是用于实现lock,Monitor等线程同步原语,Type object pointer是指向当前对象运行时类型信息的一个指针。Sync block index与Type object pointer只在CLR层面存在,对C#程序来说是透明的。但是CLR将它们暴封装后露C#,例如线程同步原语和反射API。

阅读全文

废话

BUG是任何软件都会遇到的问题。它通常是开发人员考虑问题不全面而埋下的隐形炸弹,在条件合适的时候就会爆炸;开发自己埋BUG往往比较容易除错,因为代码都是自己写的,定位问题后git blame一下就可以甩锅了;而程序依赖项里的BUG则排查起来则让人一筹莫展,尤其是在没有足够多信息的情况。

面对来自客户和QA的压力,绞尽脑汁仍无法定位问题开发们只能找借口了🤣

  • It’s a feature,not a bug.
  • That’s the design decision, so not a bug

我以前也遇到框架出问题的情况,不过都是自己改代码改出来的,倒也不是很难排查。但这次挖出来的BUG就完全不一样了

阅读全文

HttpClient是随着.Net framework 4.5一起发布的现代Http库。比起WebClient,HttpClient最大的优点就是 加入了C#5中的async/await异步方法的支持。async/await的坑暂且不表,今天就来说一说这个HttpClient

HttpClient的坑

HttpClient实现了IDisposable接口,很多小伙伴一看到IDisposeable接口就纷纷把HttpClient套在了using里边

//bad httpclient usage
using(var client = new HttpClient())
{
    //do stuffs
}

这种用法是错误的.HttpClient在设计之初被设计为一个可重用的对象,它的生命周期应该与应用程序相一致.上述错误的用法每发起一个请求就会创建一个新的HttpClient,并且在收到回复之后立即把HttpClient dispose掉。众所周知TCP连接在真正断开之前会有几分钟处于CLOSE_WAIT状态。这个状态下TCP链接并没有真正断开。短时间内大量发出Http请求会使系统可用的端口急剧消耗。

阅读全文