本文同样是笔记整理,手动输入一遍和看书的感觉还是很不一样的。文章非常好,讲的很清楚。
什么是接口? 接口是包含一组虚方法的抽象类型,其中每一种方法都有其名称、参数和返回值。接口方法不能包含任何实现,CLR允许接口可以包含事件、属性、索引器、静态方法、静态字段、静态构造函数以及常数。但是注意:C#中不能包含任何静态成员。一个类可以实现多个接口,当一个类继承某个接口时,它不仅要实现该接口定义的所有方法,还要实现该接口从其他接口中继承的所有方法。
什么是抽象类? 抽象类提供多个派生类共享基类的公共定义,它既可以提供抽象方法,也可以提供非抽象方法。抽象类不能实例化,必须通过继承由派生类实现其抽象方法,因此对抽象类不能使用new关键字,也不能被密封。如果派生类没有实现所有的抽象方法,则该派生类也必须声明为抽象类。另外,实现抽象方法由override方法来实现。
比较 相同点 都不能被直接实例化,都可以通过继承实现其抽象方法。 都是面向抽象编程的技术基础,实现了诸多的设计模式。 不同点 接口支持多继承;抽象类不能实现多继承。 接口只能定义抽象规则;抽象类既可以定义规则,还可能提供已实现的成员。 接口是一组行为规范;抽象类是一个不完全的类,着重族的概念。 接口可以用于支持回调;抽象类不能实现回调,因为继承不支持。 接口只包含方法、属性、索引器、事件的签名,但不能定义字段和包含实现的方法;抽象类可以定义字段、属性、包含有实现的方法。 接口可以作用于值类型和引用类型;抽象类只能作用于引用类型。例如,Struct就可以继承接口,而不能继承类。 规则与场合 请记住,面向对象思想的一个最重要的原则就是:面向接口编程。 借助接口和抽象类,23个设计模式中的很多思想被巧妙的实现了,精髓就是面向抽象编程,通过封装变化来实现实体之间的关系。 抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。 接口着重于CAN-DO关系类型,而抽象类则偏重于IS-A式的关系; 接口多定义对象的行为;抽象类多定义对象的属性; 接口定义可以使用public、protected、internal 和private修饰符,但是几乎所有的接口都定义为public,另外方法的访问级别不能低于接口的访问级别,否则可能导致编译错误。 “接口不变”,是应该考虑的重要因素。所以,在由接口增加扩展时,应该增加新的接口,而不能更改现有接口。 尽量将接口设计成功能单一的功能块,以.NET Framework为例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一个公共方法。 接口名称前面的大写字母“I”是一个约定,正如字段名以下划线开头一样,请坚持这些原则。 在接口中,所有的方法都默认为public。 如果预计会出现版本问题,可以创建“抽象类”。而向接口中添加新成员则会强制要求修改所有派生类,并重新编译,所以版本式的问题最好以抽象类来实现。 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。 对抽象类不能使用new关键字,也不能被密封,原因是抽象类不能被实例化。 在抽象方法声明中不能使用 static 或 virtual 修饰符。 最后还是要勤于键盘,才能深入理解啊。 参考:对抽象编程:接口和抽象类
C#中的字符串驻留
字符串string可以理解为char[],他是一个引用类型。
字符串创建 操作上类似于int,char等类型,直接进行赋值,string str=“bystander”;虽然string 是个类,但是如果你天真的使用
来构造,会导致一个编译错误。因为System.String只提供了数个接受Char*,Char[]类型参数的构造函数。 所以只能像下面这样使用,
看出来了吧,很麻烦的。所以一般还是使用第一种。
字符串恒定性 恒定性(Immutability),是指字符串一经创建,就不可改变,这是String最为重要的特性之一。具体来说,就是字符串一旦创建,就会在托管堆上分配一块连续的内存空间,我们对其的任何改变都不会影响到原有的String对象,而是重新创建的新的String对象。类似Insert,Substring,ToUpper都只是创建出了新的临时的字符串,会成为下次垃圾回收的目标。 好处:
保证了对String对象的任何操作不会改变源字符串。 恒定性还意味着操作字符串不会出现线程同步问题 恒定性一定程度上,成就了字符串驻留。 字符串驻留 CLR维护一个表来存放字符串,该表叫做拘留表(或驻留池),他包含程序上以编程方式声明或创建的每一个唯一的字符串的引用,因此具有特定值的实例在系统中只有一个。如果将同一个字符串分配给多个变量,那么CLR就会向拘留池检索相同引用,并分配给变量。
通过下面这个例子来说明:
猜猜答案是什么。。 正确答案是:True,False,True 为什么不是我们通常认为的那样呢。这就是因为字符串驻留了
缘起 String类型的特性恒定性,对字符串的任何操作都只会创建新的字符串,这会导致性能下降,而String又用的很频繁,为此,CLR使用字符串驻留来解决这一问题。为此,CLR内部维护一个哈希表,来管理其创建的大部分string对象。其中Key为string本身,Value为分配给对应的string的内存地址。
细节 CLR初始化时,创建一个空的哈希表,当JIT编译方法的时候,会首先在哈希表中查找每一个字符串常量,显然找不到任何"bystander"变量,因此会在托管堆中创建一个新的string对系那个strA,并更新哈希表,Key被赋值为"bystander",Value被赋值为strA的引用.也就是Value内保留了"bystander"在托管堆中的引用地址.
接着,JIT根据"bystander"查找哈希表,结果找到了,所以JIT不做操作,只把找到的key对应的Value值赋给了strB对象.因此,第一个输出为true,引用相等.
同样,JIT向哈希表中添加了Key为"by",Value为托管堆上"by"的地址.返回strC对象.但是注意,strD不同,JIT不检测,因为strD他是动态生成的.这样的字符串不会被添加到哈希表中进行维护,而是在托管堆中直接分配,所以第二个Console输出False.
对于第三个,我们首先看看Intern方法和IsInterned方法,对于动态生成的字符串,因为没有添加到CLR维护的哈希表,所以字符串驻留机制对其失效,但是可以手工开启,来实现高效的比较字符串相等.
两者的机制都是去哈希表中查找是否存在str字符串,找到的话也都返回对str的引用,不同的是当哈希表中没有str的话,IsInterned返回null,而Intern将把这个字符串添加到哈希表,并返回引用.注意,IsInterned返回非null并不代表两个字符串引用了相同的地址. 所以
就很好理解了.
降级论
相当精彩的一篇文章『降级论』,收藏分享。精彩的部分突出显示了。
几乎一年没有写博客了,说没时间那是借口,唯一的原因是,年纪越大越发觉自己肤浅。有些想法还没提笔,就发现很幼稚,就不敢发出来贻笑大方了。这次先给大家说个小故事:
从前有三个屌丝,聚在一起做网络,提供免费的网络服务,砸锅卖铁,通宵达旦,除了卖肾啥都做了。3年后终于做到了五百万用户,对于年轻人来说,能把五百万人玩弄于鼓掌之间,已经是很牛逼轰轰的事了,不过用户越多,成本越高,每年服务器、带宽租金、房租水电、广告运营等成本,已经达到了十七八万,屌丝们不得不面对一个终极问题:如何盈利?
屌丝们定了三盘沙县水饺,围着一箱子的冰啤酒开始计算:按照最近一月的登陆情况来看,四百万个账号已经不活跃了,真正有商业价值的只有一百万人,如 果开通xx功能,收点高级会员费,让其中1%的人升级为高级会员,每年付30块钱年费,那么每年收入就是100万x1%x30元=30万元!不错嘛, 扣除十七八万的运营成本,还剩毛利润12万,每个屌丝年底能分到4万大洋,如果按照打工者的算法,这三个人每人月薪3333元,木有奖金,木有津贴、木有任何福利,上班还得带自家的电脑。
尽管如此,屌丝们还是激动得热泪盈眶:老子有钱啦!老子有钱啦!!!那一夜,人们看到三个发疯的屌丝在屋顶翩翩起舞。
韩寒说,中国人民是最有忍耐力的族群,一点好处就感激涕零。他一定不知道,IT创业界里的屌丝,才是这群傻逼中的战斗机。他们可以平静地忍受每年都持续亏钱,而且还能信心十足的对所有人说公司的状态非常好,如果有一天居然收支平衡了,他们会激动的趁夜难眠,比北朝鲜倒掉还开心。
本文开头的三个屌丝,其实是非常幸运的,至少能做到月薪3333元。大部分的屌丝在第一年做到几万用户的时候就会挂掉,原因众多,最主要要的是意志太弱,受不了最初的寂寞;意志稍微坚强点的会在第二年第三年慢慢挂掉,原因主要是资金断裂、团队分裂;能成功熬到第四年还没饿死、还没被口水淹死、还没被肠胃病颈椎病腰肌劳损折磨死的,甚至员工不减反增的,基本上属于神仙级别了。
我为什么要说三个屌丝的故事呢。首先是因为这是身边每天都在发生的故事,其次是因为感到可惜,
IT界在我眼里一直是一个无比高级的职业,聚集着全球最聪明、最富有的人类精英。以IT创业界的青年们的智商,他们可以做成任何一件事情,包括改造银行到制造汽车到发射航天飞机 。结果这帮人却整天在蓬头垢面得为3k的月薪而挣扎,太悲催了。
为什么用悲催这个词? 如果一个人生下来就在山沟沟里,一辈子都没机会去见什么好东西,这不叫悲催,这只叫苦难;
而如果一个人生出来有一个奇怪的特异功能:皮肤出来的汗水会凝结成昂贵的水晶,本来只靠出汗就能赚钱,结果这傻逼居然觉得出汗这个行为太低级,做手术把自己的汗腺全给切了,而且丝毫没有意识到他做了什么傻事,这才叫真的悲催。
我们IT界中的很多人,生下来就是有这个出汗成水晶的特异功能的,正是因为这种与众不同,这群人能混入牛逼的大学,整天打网游还能写出像样的毕业论文, 拿到学位,进外企,考CPA,做咨询、做证券分析,研究高分子材料,做电子商务,做云计算。。。一级一级的上升,直到有一天,发现身边的人里,已经没有一个不是CPA,不是咨询师,不是高级研究员了,身边的人全是业界精英,个个都超级强悍。在这个所谓的高级圈子里,自己并没有任何过人之处,只不过是just another analyst而已。在高级圈子里拼的头破血流,最后也只能混到给台湾人整理数据而已。莫然回首,发现当年的血气方刚、年少时的无限梦想,进化成了一身肥胖的赘肉。这个时候,有个旁观者说:“升级到头了,该降级了”
当一个社会疯狂鼓吹快节奏的时候,一定需要有人来宣扬慢生活;当全社会跟打了鸡血似的吹捧升级的时候,一定需要有人来说说降级论。
IT青年们喜欢打游戏,喜欢升级。他们的人生也和游戏一样,沉醉于不停的升级中,不仅喜欢升级自己手上的技术,把MySql改成MongoDB,把Apache升级为Nginx,在Mac上装Ubuntu,Ubuntu里再装个虚拟机去跑Mac OS。。。IT青年们也喜欢升级自己的人生,从程序员升级到项目经理,再升级到技术总监或产品总监,再升级到合伙人。。。
在不断追求升级的过程中,所面临的一个很大事实是:当一个人从A刚升级到A+级的时候,其实这个人的能力层级依然只是A的层级,还未胜任A+的层级,他必须要到A+的后期,才可以胜任A+。就好像一个高中生,高考完之后,虽然理论上已经属于大学生了,但是他的实际能力依然只是高三毕业的水平,除非他全部pass了大一的期末考试。同样的道理,
这个世界上有很多人的身份和称谓,都是在描述“未来的自己”,而不是现在的自己。
当你从销售员升级为销售经理的时候,你自我感觉很好:“我现在是销售经理了”,但是这个时候 ,你并未通过公司对你作为销售经理这一年的工作成果的考核,你只是一个“未来可能是合格的销售经理”的前身。如果年终考核你失败了,那么这一年最准确的描述是:一个销售员,占了整整一年销售经理的位子,最后失败了。而且这一年一定会过的很累,因为通过考核的其他销售经理,才是真正胜任这个层级的人,跟一帮真正属于这个圈子的人厮杀,就好像拳击馆里当陪练的小角色,去和泰森比了一年的武,怎么可能不累呢?
当我07年进入互联网行业的时候,就是那个拳击馆里陪练的小角色,我被迫去跟全国各地的泰森比拼,结果累的半死。后来我开始反思最初的目标,为什么要在自己身上挂一个“拳击高手”的招牌,被那么多泰森追着打? 我把这块招牌卸了,找个完全没练武的人去比拼,不是更容易赢么?于是果断照做,去找了一个没人懂拳击的小乡村,做了纯英文的Tucia.com(需翻墙),只做国外的业务。在那个地方,作为一个知名武馆的拳击小陪练,我成了村子里拳击技术最高超的人,受人仰慕,还开武馆教人拳击,活的非常滋润,而且在教人拳击的过程中,自己的拳术也比以前提高了很多,发展出一套属于自己的拳法,我虽然进不了泰森们的大圈子,但他们也进不了我的小圈子。
关于圈子,有一个很赤裸裸的现实:不会是你进入圈子,只能是圈子进入你。很多人会四处找关系,“帮我介绍给xxx吧,我想进入你们的圈子”,这样的人是永远进不去这个圈子的,因为圈子的天性是,永远追求更高一个层级的人。而我们的大部分人,其实都在以低一级的属性,占着更高一级的位子,徘徊在更高一级的圈子边缘,与更高一级的人竞争,幻想着自己可以升级到那个圈子里去。也许永远进不去,悲催的努力一辈子;也许运气好,某一天真的进入这个圈子了,但那个时候又会有下一个目标,希望进入更高级的圈子,这是一场没有终点的战斗。永远的追求升级,永远的累。
有没有想过降级呢?
如果一个来自微软的高级工程师,辞职去一个养猪场做开放平台经理,那么他的到来不仅会让养猪圈感到无比荣幸,更是意味着,利用他在IT界训练出来的高效工作方式和逻辑思维能力,他可以掀起一场养猪行业的革命,使得20年后才会出现的人性、高效、开放、协作、健康的养殖方式提前到达。在这场革命中,他会活的非常有价值。这种价值,在原先的圈子里,是完全体验不到的,因为他此前的所有工作,只是在满身疮痍的windows系统上不停的打补丁,无论打多少都逃不开产品衰落、被人鄙视的命运。
很多人的命运,都像是上面那个微软工程师。只需要降级,就能创造更大的价值,也能获得更大的满足。那为什么不呢?为什么要死死抱着那个所谓的“高级职业”不放呢?
去年我曾犯贱去趟了移动互联网的浑水,做了个手机app,刚开始的时候感觉很高级,但很快,铺天盖地的竞争对手就出现了,我又发现自己陷入了07年一样的场景:作为一个小小陪练,我他妈的又被一帮泰森们给围住了。当泰森中的战斗机—微信,变得无比牛逼之后,我就知道,战胜这群泰森是绝对不可能的事情了。于是我再次投靠了“降级论”,把自己从牛逼哄哄的移动互联网行业,降级到了一个被人不齿的低级项目:Tucia Baby。
这个项目虽然是传统行业,但是我们基本上是按照互联网产品的思路去做的,除了拍摄需要来店里以外,其他一切,包括营销、预约、客服、后期、选片、取片、客户关系等,所有环节都放在网络上,尤其是微博(@tuciababy官网)。当然,最重要的是,作为一个脑残的果粉,我按照iPhone的做工和品质去要求每一张作品,必须达到我们能力可以做到的最好水准,不计成本的最好水准,才允许送给客户。正式接客不到两个月时间,虽然还远未达到成功,但目前已做到每天都有客户订单,财务上已实现盈利,未来相信一定会比大部分app开发者更光明。(ps:我们没有请工商、税务、城管去吃饭喝酒泡桑拿,也没有塞钱给任何政府机关。
当你的产品真的用心做到很好的时候,其实你不需要讨好任何人的。
)
这个项目让我沉思了很久:07年我曾把一个纯纯的web2.0网站做到了alexa中国区前1000名(如有质疑,请查询2010年附近的tucia.com排名),结果一路亏损,到最后只剩下一个员工;11年我把那个纯纯的app做到苹果官方推荐区免费榜的第一位(点此看截图),那段时间每天四五千iPhone安装量,结果一路烧钱,到最后濒临关闭;而如今,我只需把自己从纯纯的互联网降级下来,做一些看起来有些“低级”的项目,居然就能立即实现收支平衡。
除此以外,我还发现一个现象,
中国消费者在与奸商们的长期斗争中,已经培养出了一种非常苦B的品质:只要不被坑,他就谢天谢地。如果商家严格做到了承诺的每一件事情,客户就会感动的泪如泉涌。
如果商家不仅做到了所有承诺的事情,还很贴心的提供了一些额外的服务(比如我们给每位客户赠送非常好吃的樱桃和昂贵的进口巧克力作为甜点),那么客户就会激动的哭天喊地、奔走相告,推荐给他认识的每一个人。
其实这片肮脏的国土,就是上天赐予IT青年们的最好机会。
在一个不会练武的村子里,只要你会打两拳,你就是拳术最厉害的人;在一个没有服务意识、忽视产品质量的土地上,只要你用心做服务,用最高的标准去要求自己,你就会成为这块土地上最出色的商家;在一个没有现代管理意识,不懂网络、不懂微博、不懂用户体验、不懂口碑传播的粗犷社会里,你只需要把之前花在IT产品上的心思的10%拿过来用,就可以秒杀一切天朝对手。
所以,
IT青年们,当你在为网站的转化率苦苦思索的时候,当你在为app的活跃度辗转反侧的时候,当你在为融资计划苦苦哀求各界大佬引荐的时候,也许犯了一个错误,也许你们的脑子最值得闪光的地方,不是去悲催的IT界当炮灰,而应该是去按摩界、餐饮界、烧烤界、早餐界、理发界、家政界、按摩界、送花界、纺织界、成人用品界、现代化养殖界、有机蔬果界、个人护理界、汽车修理界。。。。与IT界相比,这些行业的确无比低级,他们的老板连qq都会发音成“抠抠”,他们的员工一辈子都没用过Email;跟他们解释什么是SEO,什么是用户体验,什么是数据挖掘,他们会在听你说完之前就开枪自杀掉。正是因为如此,这些行业才是如此的不堪一击。正是因为如此,当智商高达147的IT青年还在为3k薪水拼命、而智商不到50的烧烤店老板正坐在porsche里玩着前面那位青年开发的app的时候,我就忍不住仰望星空。
这些原始而纯粹的行业,正在等待IT精英们的降级,如同蒲公英一般的伞兵,在黑夜里从天而降,长驱直入,用最智慧的产品、最优质的服务拯救这些早就该死的行业,屌丝的生命将会绽放出银色的羽翼,无比丰满,无比性感。
最后注意,请珍惜生命,远离我的微博:@meditic
移动设备电池白皮书
资源来自:金山网络
我比较认真的读完了这本小册子,确实收获还是蛮大的。前几天有个朋友问我电池的事情,我以前看过电池的一些保养的。当时就知道锂电池是首次使用是不需要进行12小时充电的。。看到这本小册子的时候,证实了我没乱讲哈。。
然后里面还说道一个就是很多人不相信软件能够保养电池。其实真的是可以的。。理由不赘述。你可以自己读一读。。我自己感觉对普通用户很有用的是30页的那一节。讲到的问题有;
电池管理类软件对电池寿命没用? 充电习惯对电池寿命没有用? 一块电池都只够安卓撑一天? 提示电池充满就可以马上拔掉电源 ? 不管怎么用待机时间都一样? 手机还有一半电量的时候不必担心? 新电池前3次需充满12小时? 涓流充电有用吗? 手机电池充一夜也没什么危害? 边充电边使用对电池无伤害? 突然断电再立刻充上会伤害电池吗? 充电不饱和会伤害电池吗? iPhone和iPad的充电器可以混用吗? 经常把电用光再充对电池好不好? 书籍下载:[移动设备电池使用白皮书](http://115.com/file/ancame68# 移动设备电池白皮书.pdf)
C#中XML和二进制的序列化
看书的时候,看到的。然后感觉书上的写的不清楚,于是自己写了一下。还真的有问题。 要进行序列化和反序列化,首先要定义一个可以序列化的类,方法是在类的声明前加上特性 [Serializable] 定义了一个简单的用户类,需要注意的是私有字段是不能序列化的,只有公有字段和公有属性才可以。如下
注意,书上有个例子没有给出默认的构造函数,实际测试时如果没有默认构造函数,是不能执行xml序列化的。注意。
然后就导入需要的命名空间。 需要导入
分贝对应文件操作,二进制序列化和xml序列化
为了方便,我封装了四个静态函数,用于实现序列化和反序列化。
代码比较简单。 最后是一个简单的测试。
CSV批量导入解决
最近的一个事就是那个诡异的CSV导入,后来决定用最笨的方法。就是readline,然后确实是可以正常识别了。思路就是一行行读入,然后构造sql语句,保存为sql文件,然后去批量执行sql文件。其实在codeproject找到了一些类似的工具,都有不如意的地方,但是时间关系还没能自己去定制,这件事完成后,就去完善一下大牛们的工具。
因为是多个csv文件,每个文件对应于我们想建的一个表,实际是大约2000个csv文件,每个文件大约4000行数据,构造成对应的sql语句比较简单,需要注意的就是如果sql server表中的字段和关键字重名,那么需要加[],比如我们有个字段是open,那么实际sql语句中使用的时候,比如
简单的读写以后我们构造了2000个sql文件,然后我们需要执行这些sql文件。。必然需要写个代码来批量执行了。。为此,我先用C#生成一个批处理文件,然后来执行
简单封装了一下,输入参数是文件夹。里面包含我们的所有sql文件。输出为一个批处理文件。。后来。执行下生成的bat文件就可以了。。
600M的sql文件执行起来三个多小时。。因为只算一次,所以就不考虑优化了。。鄙视我们吧。
《Effective C#》Item 9:区别和认识四个判等函数
.Net有四个判等函数?不少人看到这个标题,会对此感到怀疑。事实上确是如此,.Net提供了ReferenceEquals、静态Equals,具体类型的Equals以及==操作符这四个判等函数。但是这四个函数之间有细微的关系,改变其中一个函数的实现会影响到其他函数的操作结果。
首先要说的是Object.ReferenceEquals和Object.Equals这两个静态函数,对于它们俩来说,是不需要进行重写的,因为它们已经完成它们所要得做的操作。
对于Object.ReferenceEquals这个静态函数,函数形式如下:
这个函数就是判断两个引用类型对象是否指向同一个地址。有此说明后,就确定了它的使用范围,即只能对于引用类型操作。那么对于任何值类型数据操作,即使是与自身的判别,都会返回false。这主要因为在调用此函数的时候,值类型数据要进行装箱操作,也就是对于如下的形式来说。
这是因为对于n这个数据装箱两次,而每次装箱后的地址有不同,而造成Object.ReferenceEquals( n, n )的结果永远为false。
对于第一个判等函数来说,没有什么好扩展的,因为本身已经很好地完成了它所要做的。
对于第二个Object.Equals这个静态函数,其形式如下:
按照书中对它的分析,其大致函数代码如下:
可以说,Object.Equals这个函数完成判等操作,需要经过三个步骤,
第一步是需要根据对象所属类型的==操作符的执行结果;
第二步是判别是否为null,也是和第一步一样,需要根据类型的==操作符的执行结果;
最后一步要使用到类型的Equals函数的执行结果。
也就是说这个静态函数的返回结果,要取决于后面要提到的两个判等函数。类型是否提供相应的判等函数,成为这个函数返回结果的重要因素。
那么对于Object.Equals这个静态方法来说,虽说接受参数的类型也属于引用类型,但是不同于Object.ReferenceEquals函数,对于如下的代码,能得出正确的结果。
这是因为在此函数中要用到具体类型的两个判等函数,不过就函数本身而言,该做的判断都做了,因此不需要去重载添加复杂的操作。
为了更好的述说剩下两个函数,先解释一下等价的意义。对于等价的意义,就是自反、对称以及传递。
所谓自反,即a == a; 而对称,是a == b,则b == a; 传递是 a == b,b == c,则 a == c; 理解等价的意义后,那么在实现类型的判等函数也要满足这个等价规则。 对于可以重载的两个判等函数,首先来介绍的是类型的Equals函数,其大致形式如下:
如上增加了一个类型检查,即
这部分,这是由于子类对象可以通过as转化成基类对象,从而造成不同类型对象可以进行判等操作,违反了等价关系。
除此外对于类型的Equals函数来,其实并没有限制类型非要属于引用类型,对于值类型也是可以重载此函数,但是我并不推荐,主要是Equals函数的参数类型是不可变的,也就是说通过此方法,值类型要经过装箱操作,而这是比较影响效率的。
而对于值类型来说,我推荐使用最后一种判等函数,即重载运算符==函数,其大致形式如下:
对于一个值类型而言,其的大致形式应该如下:
由于==操作与!=操作要同步定义,所以在定义==重载函数的时候,也要定义!=重载函数。这也是.Net在判等操作保持一致性。那么对于最后一个判等函数,这种重载运算符的方法并不适合引用类型。这就是.Net经常现象,去判断两个引用类型,不要用==,而要用某个对象的Equals函数。所以在编写自己类型的时候,要保留这种风格。
那么对于以上介绍的四种判等函数,会产生如下类似的对比表格。
操作结果取决于
适用范围
建议
Object.ReferenceEquals
引用类型
Object.Equals
无限制
类型的Equals
无限制
**类型的==**重载无限制
来源:http://blog.csdn.net/knight94/article/details/1050901
Unable to read file Data_EGCITest解决方法
今天做的是使用matlab进行协整检验,好吧。。听起来似乎很厉害的样子,其实,我也不太清楚协整到底是干嘛呢。不过经管的各位很给力。 想来协整检验matlab是可以做的。所以就去查matlab是不是有这个函数,结果是有的。egcitest,但是具体的参数还是景观的朋友看懂的。
早上3点多起床,看matlab的书,然后早上看完了。基本上熟悉了matlab的操作。然后就开始写这个。大致的流程和昨天的那篇文章是一致的。但是matlab生成的dll文件在C#里面调用始终会提示这样一个错误。:
组合了几个关键字进行搜索,发现了这篇文章,翻译过来很简单。
错误提示说的那个Data_EGCITest是一个名为Data_EGCITest.mat的文件,位于$MATLABROOT/toolbox/econ/econ/Data_EGCITest.mat目录下,$MATLABROOT指的是你matlab的安装路径。在你build 工程的时候,在下图中,记得添加这个文件。
然后build生成的dll文件就可以正常在C#里使用了。
中间走了很多弯路。因为我想既然matlab都编译生成了dll,那么dll应该没问题。然后我就把精力放在了C#那边。。结果后来折腾了很长时间,才发现是这边的问题。。坑爹。。
协整检验的代码就不发了。和题目没关系。。 参考: http://www.mathworks.cn/help/toolbox/econ/egcitest.html
C#调用MatLab实现N阶幻方
MatLab的计算能力太强大了。最近需要通过C#来调用MatLab来进行一些计算,可是MatLab没用过。安装文件在我硬盘里躺了整整一年。
我们希望的是由外部程序调用MatLab函数。所以。希望可以完全脱离MATLAB环境,实现软件的快速开发。为此需要先介绍一下MCR。
MCR简介 MCR的全称是MATLAB Compiler Runtime,即MATLAB编译器运行时。是一个由MATLAB共享类库构成的执行引擎,他能够使MATLAB文件在没有MATLAB的机器上运行。这一点和.NET Framework相对于.NET程序一样,即为程序的运行提供了底层支持。当发布程序的时候,需要将MCR也打包进来,这样没有MATLAB的机器上也能执行,MCR随MATLAB软件一同发布,可以在MATLAB中输入命令“mcr”或者“mcrinstaller”获取其保存路径:
根据上面的运行结果,可知该文件的完整路径是:
MWArray API简介 MCR包含了文件MWArray.dll,该文件中的API承担了用户程序和MCR之间数据交换的任务,因此,每一个独立文件都需要包含对该文件的引用,否则程序就不能使用MATLAB中的函数,为使用该文件,需要先使用上一步找到的安装MCR,我安装在D:\Program Files\MATLAB\MATLAB Compiler Runtime目录,然后该dll该文件在安装完MCR后位于:
另外,该文件中有两个重要的命名空间,MathWorks.MATLAB.NET.Arrays和MathWorks.MATLAB.NET.Utility,Arrays命名空间下的类提供从其他任何兼容CLS(Common Language Specification) 语言访问MATLAB中数组的功能,这些类支持数组格式化、类型的特定索引和错误处理的功能。而Utility命名空间下的类提供了对MWArray类架构和MATLAB公共运行时的托管API的通用支持。
实施 为了将MATLAB中的程序作为组件提供给其他.NET程序使用,需要做两方面的工作:
1.将M文件打包为与.NET兼容的程序集
2.在外部程序中添加对程序集的引用
MATLAB端的工作 以我这个功能为例。打开MatLab,然后File->New->Deployment Project.然后在Type里选择.net Assembly,Ok即可。我选择的工程名是test,注意,这个test就会生成一个名为test.dll的程序集,所以起个好名字,,我没起好。如图1 然后在图2的视图中定位到你选择的工程目录,并依次点击。 添加一个test.m的文件。图3 这个名称随意。但是要注意,这个名字必须和你里面将要写的那个函数名称一致,这个很好理解。好了以后,双击test.m就会打开。输入
创建一个test方法。该方法在C#调用的时候要用到,接受一个参数,然后输出一个幻方。保存关闭m文件,然后回到上图,双击test.prj也就是工程文件。 来到图4 点击Add Class,就是向test.dll的程序集中添加类。我添加了一个类叫做Func1.这个类用来在C#中创建一个对象,然后调用test(n)这个函数,然后出现Add Files,点击打开浏览框,把刚才写好的test.m选上。就可以了 最后看窗口右上角,,点击那个build图标就ok,等个几分钟,就会在目录里生成test.dll文件了。图5
VS端的代码 现在,打开vs,创建C#工程,添加两个引用,分别是MWArray.dll和test.dll,添加引用的方法就是在解决方案资源管理器中,的引用上,点击,然后添加引用->浏览->找到这两个dll,为了方便,我一般会把这两个dll复制到我的C#工程目录里,然后添加引用,如前面所说,MWArray.dll里有两个命名空间,我们使用using语句都添加上。也包括生成的test.dll
然后设计C#界面,很简单的拖一个界面,图6 然后单击事件代码:
看到test有两个参数,第一个参数是指返回结果书,我们只需要一个就好了。所以为1,后面那个是阶数了。运行结果如图7:
注意程序在初始化自定义类Func1时会花费较多时间,大约持续2~3秒钟,程序如同假死一般,但第二次点击按钮反应却很快. 参考: http://www.360doc.com/content/12/0530/10/9587654_214689438.shtml
C#中的静态与非静态
为什么要分静态和非静态 在面向对象的世界里,大部分的情况都是实例特征主宰天下,类相当于一个类型模板,而对象则是类特征的拷贝,并且独立于其他对象来操作这些特征,但是在某些情况下,需要某些特征被所有的对象共公有,因此有必要实现一种基于类的特征,而不是基于实例对象的特征机制,这就是静态特征。
1.静态类和非静态类 一个类如果包含静态成员和静态方法,那么该类就可以定义为静态类,定义方法是在类定义前加上static,比如
比较: 静态类只能包含静态成员和静态方法,否则会抛出编译错误,而非静态类既可以包含非静态成员和非静态方法,还可以包含静态成员和静态方法。但不能作用于静态只读字段。 静态类不可实例化,非静态类可以实例化,不管是静态类还是非静态类,对静态成员和静态方法的调用都必须通过类来实现访问。 相对于非静态类来说,静态类有一些特点值得应用,比如System.Console这个典型的静态类。 如果一个类只包含静态成员和静态方法,就应该将该类标记为static,并提供私有的构造函数来避免用户实例创建对象,这也是MonoState模式的体现。 2.静态构造函数和实例构造函数 静态构造函数,只能用于初始化类中的静态成员,包括静态字段和静态属性,静态构造函数不能带参数,不能有访问修饰符也不能被手工调用,通过是在.net运行库第一次调用类成员之前执行。其中,实例构造函数中也是可以初始化静态成员的。
比较 静态构造函数,可以和无参的构造函数共存。虽然参数列表相同,但是二者的执行顺序不同,静态构造函数在运行库加载类时执行,而实例构造函数在实例创建时执行。 静态构造函数,只能对静态成员进行初始化操作,不能作用于非静态成员,而实例构造函数二者都可以,当然如前面所说,对静态只读字段就不可以了。 静态构造函数只被执行一次,而且.net运行库也不知道什么时候会被执行,而实例构造函数可以在多次实例创建时被执行多次。 一个类只能有一个静态构造函数,但是可以有多个实例构造函数。 一般来说,简单的静态成员可以在声明时就进行初始化,而复杂的静态成员则选择在静态构造函数中进行初始化较佳。 3.静态成员和实例成员 静态成员主要包括静态字段和静态属性,静态成员可以实现在类中能够被所有实例对象共享的数据。例如一个缴费登记系统中,消费总额作为所以消费的综合,静态成员来实现就有很好。没有不必要的数据冗余。
比较 静态成员包括静态字段和静态属性,静态字段一般实现为private,而静态属性一般为public,以体现类的封装原则。 静态成员和类关联,不依赖对象存在,只能由类访问,而不能由对象访问,实例成员和具体的对象关联,只能由对象访问,不能由类访问。 静态成员属于类所有,不论创建多少个实例对象,静态成员在内存中只有一份,实例成员属于对象实例所有,每个都有其对应的内存区域。 4.静态方法和实例方法 类似于静态成员共享数据段,静态方法共享代码段,静态方法以static标识。
比较 性能上,静态方法和实例方法差别不大,所有方法,不管是静态的还是非静态的,都是在JIT加载类时分配内存,不同的是静态方法以类名引用,而静态方法以对象引用,创建实例时,不会再为类的方法分配内存,所有的实例对象公用一个类的方法代码,因此,静态方法和实例方法的调用,区别仅在于实例方法需要当前对象指针指向该方法,而静态方法可以直接调用,性能上差异微乎其微。 静态方法只能访问静态成员和静态方法,可以间接通过创建实例对象来访问实例成员和实例方法,而实例方法可以直接全部。。 静态方法只能由类来访问,实例方法只能由对象来访问。 静态方法中不能使用this关键字,否则编译错误,而实例方法中可以引用。 静态方法不能被标记为virtual,abstract或是override,静态方法可以被派生类访问,但是不能被覆写。 Main方法是静态的,因此Main方法不能直接访问Main所在类的实例方法和成员。 鉴于线程处理的安全性,应该避免提供改变静态状态的静态方法,因为,如果多线程同时访问该段代码,可能造成线程处理错误,因此,静态状态必须是线程安全的。 静态方法适合系统中边缘性的非业务需要,例如通用的工具类。