其实老实说各种奇淫巧技我见得多了,以前也写得多。
各种奇淫巧技譬如说之前被各种递归调用实现斐波那契数列的例子弄烦了,随手用C#写的迭代算法:
int a = 1, b = 1; while ( b > 0 ){ Console.WriteLine( a ); b = a + (a = b); }//循环条件的b>0是溢出就终止。
很多小白看到这种代码一般都会顶礼膜拜,惊叹无比,一般在论坛上会这样形容:不到十个字符就完成了斐波那契迭代中的累加和推移操作,真是神一样的代码。
不过这段代码我可不保证在C/C++编译器上能得到确定和同样的结果。So,别学这个,你要在生产环境这么写信不信我把你赶出去。
其实呢这里用到的赋值子表达式是类C语言最好玩的奇淫巧技之一,最普通的玩法有赋值且返回:
return service = GetService();
或是赋值并作为循环条件判断:
while( ( data = Read() ) != null )
或是连续赋值:
i = j = 1;
赋值子表达式的玩法很多,还有一个经典的是不使用第三个变量交换俩变量这种无聊的需求
a = b + (b = a) * 0;
温馨提示,这个也别学,否则被老大从窗户扔出去本人概不负责。
学会了这些奇淫巧技,就足够写出各种让小白程序员惊叹的代码了。不过在这里我想说的是,真正的精彩的代码,不在于这些奇淫巧技。
真正牛逼的技巧不在于看起来多牛逼,而是用起来特别爽,突然发现我操这个设计太棒了。
譬如说LINQ的链式调用:
var result = data .GroupBy( item => item.Name ) .Where( group => group.Count() > 0 ) .OrderBy( group => group.Count() ) .Select( group => group.Key );
看起来平平无奇,链式调用没啥稀奇,函数式语法没啥稀奇,但是真正做出来让程序员玩的爽,让别人用的时候有一种我操这个设计太棒了,不容易。
再比如说LINQ for XML的Add方法可以一次性把所有的子元素,子元素的子元素....全部搞定
document.Add( new XElement( "Member", new XAttribute( "name", "Ivony" ), new XElement( "Role", new XAttribute( "admin" "true" ), new XText( "Administrator" ) ) ) );
譬如说async、await语法,譬如说DLR,都在此列。
好吧,最后夹带一些私货好了,在我的类库里面,提供了一个扩展方法,这个扩展方法简单到只有一行代码:
public static T CastTo<T>( this object obj ) { return (T) obj; }
看起来太TM弱智了,这种扩展方法存在的意义是什么?
这个扩展方法的意义对于很多场景来说,极其深远,其实这个扩展方法是为了改善C#语言坑爹的强制类型转换语法的。
我们经常会遇到这样的场景,通过某个表达式获取一个对象,然后强制类型转换,再调用其中一个成员方法或是赋值给某个属性。
首先我们会写一个表达式获取对象:
GetDataObject()|
那个|表示光标所在的位置(下同,不再赘述)。
然后我们发现,这个对象TMD类型不对,我要强转一下:
(Member)| GetDataObject()
然后把光标挪到前面去,输入括号类型括号。
然后又发现强转的优先级低于.运算符,所以我还得改一下:
((Member) GetDataObject()).Name|
这下终于完事了(注意过程中的光标跳跃)
当然,有经验的程序员一般会起手直接双括号写类型,再写表达式。
((Member) |
但很多时候,你不可能老是这样预判,尤其是在表达式特别长的时候,来回的光标跳动,莫名奇妙的括号,都会带来各种恶心的事儿:
((Member) Db.GetEntities( "SELECT * FROM Members WHERE MemberID = xxx" ).Filter(xxx).(xxx).....
而这个扩展方法解决了这个问题,用极其简单的方式,它使得
((Member) GetDataObject()).Name
可以写成:
GetDataObject().CastTo<Member>().Name
表面上看起来,代码量更多了,尖括号输入也不如圆括号方便。
但实际上它降低了括号嵌套的层次,避免了光标乱窜,不打断程序员的思路。
最后小声说一句,其实前端写的JS脚本经常让我各种惊叹无比,要找惊叹无比的代码去翻各种前端脚本库一找一个准,,,,