Shenghe's Blog

我的照片
姓名:

I worked in Aspen Iechnology Inc. My work focus on InfoPlus.21

2008年12月30日星期二

查内存覆盖--从以前的帖子里总结的

 
 
我的实践:
1,查找泄露:首先查找内存泄露,内存泄露往往能提供内存覆盖的线索,比如:应该释放A,结果错误的释放B,导致A泄露、B破坏。
2,使用工具:用Numega检查看能不能报错。
3,搜索法:查找delete,memcpy,free三个函数和线程相关函数,检查是否有问题;
4,猜测遍历法:根据对出问题代码的怀疑程度,依次删除这些代码,直到不再出现覆盖位置,找到对应的问题代码。
不知道这算不算方法
1 定位被覆盖的内存地址
2 开始调试,在memory窗口中观察该地址内存的变化
3 若观察到在两个断点之间内存被覆盖了,则可以逐步缩小断点范围,找到发生覆盖的代码
4 可重点留意数组操作和字符串
5 如果是在一个循环中发生覆盖(例如在循环中写数组溢出),需要利用条件断点功能(当 i = xx 次的时候断住),省得你按很多次F5
以前遇到覆盖好像是这么查的。。。快2年没写大段代码了,忘得差不多了。

1,(内存泄漏)根据 vc ide debugger 的 memory leak dump 判断以及检查内存泄漏。有的时候由于
内存覆盖而无法得知文件名,这是可以查找所有的new, 根据 new 所在的代码行 比对 dump 确定泄漏
的位置。
2,(内存覆盖和内存泄漏)使用 numega boundschecker。
3,(内存泄漏)使用对象计数器。如果怀疑存在对象内存泄漏的话。在构造函数中计数器 ++, 在析
构函数中 对象计数器 -- 。
4,(内存覆盖和内存泄漏)进行大量反复的操作,用 task list 观察是否内存一直在增加。
5,防止内存泄漏的方法。
a)分配缓冲区的时候避免使用 new,而要使用 CArray 或者 vector 等动态数组。
b)一旦使用一个 new ,一定要立即考虑它的 delete。
// 原来是说内存覆盖阿。
6,内存覆盖严重的时候,往往导致系统异常,无法调试。这个时候需要采用 log file, console log
, beep 等方法。用大量的 print 输出,确定执行流,进而定位崩溃位置。采用下面代码定义log宏,
详见附录。
#if USE_SS_LOG_TRACE
#define SSLOG g_log.Log
#else
#define SSLOG 1 ? (void)0 : g_log.Log

2008年12月25日星期四

如何做一个好的Team Leader?

我开头把:
关心你的Team Member---具体怎么关心?不知道,呵呵:)

合理的分配工作:不要太多--他们会累得怨恨你,不要太少---没事干停难受,如何把握这个度?不知道,呵呵

要引导他们不断进步,给他们指点方向:该学习什么?它自身情况应该注意提高什么?这样他会信赖你,会把你当朋友,以后相处和安排工作会好点

.......还有很多

大家不要藏私阿,呵呵,分享以下

--------------------------------------------

From Zhang Min:

我觉得带team不同的人有不同的方式,我主要注意几点:

1 了解团队各人的特点,注意整体搭配效果;

2 让大家明确目标,各人的工作要可度量,团队的成绩也要可度量。工作既要做实,也要做到面上,毕竟你代表了许多人的利益;

3 时刻注意工作进度,有问题及时解决,该咋办咋办,脸皮要厚,为集体服务;

4 注意自我修养,以身做则;

5 多跟你的老板混混;

6 给下属多点信任,不要越俎代庖,技术出身的容易犯这个毛病。

 

--------------------------------------------

From Shenghe:

我继续:
1,要把自己也作为团队的一部分,荣辱与共。就是把自己的利益和其他人放在一起,才能获得信赖和尊敬
如果计较自己的得失,而让你的队员不爽,那会让人瞧不起

---------------------------------------------

From Zhang Min

1 不光是根据各人特点分配工作,也包括队伍成员的挑选去留;

2 怎么量化要站在boss的角度来看。一堆枯燥的数字也不一定能打动老板。应该说,要老板看到你工作的量;

 

---------------------------------------------

From Zip:

这里面很多东西只能意会,具体说出来往往别人会理解成另外一种意思,最好的方法是实践-->总结-->反省-->实践-->总结-->反省-->
...要结合自己所处的环境。比如说,你手下人每月挣3k,和你手下人每月挣10k,这是两种相差非常大的环境,同样一句管理学的箴言在有着这样差别
的两个环境下的含义和运用,只能自己去悟啦。

市面上有很多各式各样管理的书籍,这里我推荐一本,《高效能人士的7个习惯》,觉得值得看一看,我拿到这本书很久了,不适合一口气读完,所以我也还没读
完,有空的时候会翻一翻,看上一两节。

 

-------------------------------------------------

From Shenghe:

看到哟句话:

领导技术就是团结你的队员一起奔向美好的未来

 

我觉得很有道理

 

首先是要搞清楚你的未来--目标,愿景

2008年12月23日星期二

构造函数中为什么不适合放一些比较昂贵的操作

构造函数中为什么不适合放一些比较昂贵的操作
例如我有一个数据库类
public class DataBase
{
         public DataBase( string serverName )
         {
              .........//连接数据库
         }
}

这样设计有什么不好的?

------------------------------------------------
from Zip
<Framework Design Guided Line> 中有一条建议就是 lazy constructor

-----------------------------------------------
from Shenghe
呵呵
就是说只有在需要的时候才去执行相应的操作,是把?
恩,是个理由

但是对这个例子来说,创建一个这样对象,
然后没有联接数据库是没有什么意义的
那这种情况的话,我直接在构造函数中执行这样的操作有什么问题呢?
-----------------------------------------------
from Zip
也没有什么不好,事事无绝对,
只是遵循一定的规则可以更多的避免将来可能的错误,这些规则都是经验总结,今天不明白他的精妙没关系,或许有一天就能明白了,先按他说的做,至少不会比自己的方法更糟糕。

---------------------------------------------
from Dave
不懂c#.
在c++里面,构造函数没有返回值,
所以尽量不把操作放到ctor里,除非使用
exception

-------------------------------------------
----------------------------------
from Shaking
构造函数产生 exception  会带来很多不便。

----------------------------------
from Shenghe
例如我们来设计FileStream
构造函数传入一个文件路径,我感觉这个时候如果检验路径是否存在,如果不存在就抛出异常很合理阿

当然也可以在open的时候抛异常

-----------------------------------
from Shaking
我遇到过几个例子,构造函数中做了太多事情,导致了麻烦。但我不知道是否有一般性的原则,指导构造函数所应该做的内容。

-----------------------------------
from YangZhiqiang
理论上来讲,构造函数只是让你构造一个对象,
从这个职责上来讲的话,只要构造了这个对象就可以了。而使用这个对象的人也假定你在里面只做了简单的初始,没做什么复杂的东西。主要的其他的动作放到其他函数里执行最好。

要理解这个比较困难,从面向对象的角度来讲的话,类提供了很多的函数,这些函数值应该做这些函数规定的事情,而且值应该做这个函数规定作的事情,这样才能在协议的基础上而不是在实现的基础上设计系统。构造函数也是这样的,从协议层次上来讲,构造函数就是做初始化相关东西的,不应该做其他的东西。你如果要打开数据库,最好加一个明确的方法,这个方法用来打开数据库。这样从协议的层次上来讲变得完全了,你从构造函数里搞得话,缺少了数据库打开的操作,这样的类看起来不是很好。

还有,在设计类的方法时,操作尽量的更小颗粒,就是把一些操作尽量分解成多点方法,这样给用户提供了更好的可控性。当然也曾加了使用的麻烦性,这样可以通过一个更大的方法来实现。看起来复杂了,但是做出来的类比较好用。也比较健壮。

不管是C++还是Java还是C#,只要是面向对象的语言都是差不多的,系统要建立在协议的基础上,这样造出来的系统比较健壮。每个类,每个模块,每个运行的程序,每个计算机什么的都建立在协议的基础上运行,这样整个系统具有很强的Flexible和健壮性。就像网络建立在TCP等协议上一样,即使不同的操作系统都可以搞到一起。文本文件建立在文本协议的基础上,搞到哪里都可以打开,不管内容是什么样的。

系统耦合性好不好要看组成的系统间的协议好不好,性能好不好,看组成系统的组件的性能好不好。协议好的话,系统通过不停的替换组成系统的组件可以达到好的性能。如果协议不好的话,整个系统进化起来就比较困难。也就很快就发展到了协议的极限。

上面说的就是面向对象设计时,协议的重要性。大家都遵守的系统的协议,整个系统才能很好的达到要求。构造函数也是一个协议,所以最好遵守这个协议。

题外话:可能语言的设计者就设定下了一个构造函数只能作简单的操作,所以对构造函数支持的比较少,或者做了其他的一些处理,这样导致构造函数出问题时,不如普通函数好处理。这也是一个协议。虽然只是潜规则。

------------------------------------
from Shaking
这方面会产生一些模糊和混淆。
比如,某对象,用来封装数据库,则连接数据库看起来就是天经地义的 "构造" 任务。
不过,我仍然认为,应该把构造函数做成永远不会构造失败的。

另外,我对 exception 颇有戒心。在使用中,会有很多陷阱。要真正正确使用异常并不容易,而且由于一场先天的特性,有些陷阱难以避免。

-------------------------------------
from YangZhiqiang
其实程序怎么做都是无所谓,呵呵,这个没有可不可以的问题。关键是如何做好,这里面有很多的学问,完成一个功能有很多方法。完成功能只是其中的一个,考量一个系统好坏有很多指标,系统地可进化性,稳定性,性能,当然还有钱了。呵呵。钱少的时候,在构造函数里做初始化也无所谓了,玩笑了。在这里面做初始化不是不行,是不推荐。可能会导致问题,具体有什么问题,你可能碰得到也可能碰不到,系统小的时候什么问题都没有,大了可能出问题。你在构造函数里初始化一个巨大的数据库,搞不好会出人命。初始个小的数据,也不会有问题,而且这样做起来作程序的效率相对来说要高一些。呵呵,造大厦由大厦的造法,造民宅有民宅的造法,关键还是要合理。

--------------------------------------
from Shenghe
Do minimal work in the constructor. Constructors should not do much work other than to capture the constructor parameters. The cost of any other processing should be delayed until required.
Do throw exceptions from instance constructors if appropriate.
MSDN上的原文

-------------------------------------
from Shaking
有没有提出理由呢?
虽然我非常支持 ctors 应该做最少的事情。但我没有很强的理由。所以很想知道专家是什么意见。

我认为

   1. ctor 应该做最少的事情
   2. ctor 做的事情,不应该失败。少做事情,只做最简单的事情,以便保证成功。




Win Form程序如何记录自定义信息?


正解!应该适用于任意类型的.NET工程,我刚刚试试了Console Application,可以这样。

简单总结一下此方法,基本步骤是:
1,在你的工程上右键单击"Properties";
2,在工程属性设置也上,点击"Settings";
3,如果你从未使用过settings,这里会出现一个链接,阅读一下,单后单击它新建一个setting;
4,在你的代码中如cao说说那样,就可以使用这个类了。


On 11月5日, 上午9时02分, "shenghe cao" <caoshen...@gmail.com> wrote:
> Add strong-typed setting items to Project Setting panel and they can be
> accessed directly from code like this:
>
> WindowsFormsApplication1.Properties.Settings.Default.MySetting = "Test";
>
> WindowsFormsApplication1.Properties.Settings.Default.Save();
>
> Be aware that there're two types of settings: user-based and
> application-based.
>
> 我同事的回答,不知道好不好用
>
> 2008/11/4 michael zhang <mcw...@gmail.com>
>
> > 是,我用了Application.CommonAppDataPath,然后在里面自己写了个xml。不过这样总是不太爽。
> > 2008/11/4 shenghe cao <caoshen...@gmail.com>
>
> > 干脆自己写个XML文件来记录把
> >> C#访问XML 比C++方便
> >> 用XmlSerializer,创建一些自己的类加上一些属性就可以搞定
>
> >> 其他的我问了下其他同事,目前还没找到好的方法
>
> >> 2008/11/3 michael zhang <mcw...@gmail.com>
>
> >>>  在用C#写WinForm程序时,我想保存一下用户设置,以便下次程序启动后能继续生效。麻烦大家给推荐个正解。
> >>> win32程序好像有个WriteAppProfile()之类的方法,可以写在一个ini文件里,另外还可以写注册表。
>
> >>> 不知道现在的WinForm程序推荐做法是什么?莫非是用Application的静态方法CommonAppDataPath返回程序文件夹,然后自己写个记 录文件?



Effective C# 原则36:利用.Net运行时诊断

Effective C# 原则36:利用.Net运行时诊断

Item 36: Leverage .NET Runtime Diagnostics

当有问题发生时,它们往往并不是在实验的时候发生的,机器有轻松调试的工具。在很多实际情况中,你不好修正的问题总是发生在用户的机器上,那里没有调试环境,也没有好的方法计算出问题的情况。在实际情况中,有经验的开发人员会创建一个方法,让系统在运行时捕获尽可能多的信息。.Net框架已经包含一些类集合,利用这些集合,你可以做一些通用的调试。而且这些类可以在运行时或者编译时进行配置。如果你利用它们,你就可以轻松的发现在实际运行时的问题。使用框架里已经存在的代码,你可以发送一条诊断信息到一个文件,或者到调试终端。另外,你还可以为你的产品指定特殊的调试输出级别。你应该尽快的在你的开发环境中使用这些功能,以确保你可以利用这些输出信息来修正在实际运行中没有预料到的一些问题。不要自己写诊断库除非你已经明白框架已经提供了哪些。

System.Diagnostics.Debug, System.Diagnostics.Trace和System.Diagnostics.EventLog类提供了你在运行程序时要创建诊断信息的所有工具。前面两个类功能是基本上是一样的。不同之外是Trace类是由预处理符TRACE控制的,而Debug类则是由DEBUG预处理符控制的。当你用VS.net开发一个项目时,TRACE符号是同时在调试版和发布版中定义的。你可以为所有的发布版使用Trace类来创建诊断信息。EventLog类提供了一个入口,通过这个入口,你的程序可以写一些系统日志。EventLog类不支持运行时配置,但你可以把它封装到一个统一的简单接口中。

你可以在运行时控制诊断输出,.Net框架使用一个应用程序配置文件来控制变化多样的运行时设置。这个是一个XML文件,在主应用程序运行时的目录中。这个文件与应用程序同名,但添加了一个.config后缀。务更制块例如MyApplication.exe 可能会有一个MyApplication.exe.config的XML文件来控制它。所所有的配置信息包含在一个configuration节点中:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

</configuration>

.Net框架使用预定义的关键字来控制框架中一些类的行为。另外,你可以定义你自己的配置关键字和值。

你可以组合输出开关和Trace.WriteLineIf()方法来控制应用程序的输出。你可以在应用程序外以默认的方式关闭这个输出,以便应用程序得到最好的性能。当发现问题时,你可以打开这个输出用于诊断和修正在实际中遇到的问题。WriteLineIf()只有在表达式为真时才输出:

bool _printDiagnostics = true;
Trace.WriteLineIf( _printDiagnostics,
  "Printing Diagnostics Today", "MySubSystem" );

你所创建的输出开关用于控制输出的级别,一个输出开关可以是由应用程序配置文件定义的变量,可以是五种状态之一:关闭(Off),错误(Error),警告(Warning),信息(Info)和详细(Verbose)。这些状态是环境的一部份,而且它们的值可以是从0到4。这样你就可能为所有的子系统信息创建一个控制。 定义一个输出开关类然后初始化它就可以创建一个开关了:

static private TraceSwitch librarySwitch = new
  TraceSwitch( "MyAssembly",
  "The switch for this assembly" );

第一个参数是开关显示的名字,第二个参数是描述。这样,在运行时可以在应用程序配置文件中配置它们的值。下面就把librarySwitch设置成Info:

<system.diagnostics>
  <switches>
    <add name="MyAssembly" value="3" />
  </switches>
</system.diagnostics>


如果你编辑了这个配置文件中开关的值,那么就修改了所有由那个开关控制的输出语句。

另一个任务:你须要配置你的输出到什么地方去。 默认是一个链接到Trace类上的监听者:一个DefaultTraceListener对象。DefaultTraceListener发送信息到调试器,而且在它的失败方法(断言失败时调用)会打印一些诊断信息然后终止程序。在产品发布环境中,你不可能看到这样的信息。但你可是以配置不同的监听对象到产品发布环境中:那就是在应用程序的配置文件中添加监听者。下面就添加了一个TextWriterTraceListener 到应用程序中:

<system.diagnostics>
  <trace autoflush="true" indentsize="0">
    <listeners>
      <add name="MyListener"
        type="System.Diagnostics.TextWriterTraceListener"
        initializeData="MyListener.log"/>
    </listeners>
  </trace>
</system.diagnostics>


TextWriterTraceListener把所有的诊断信息到打印到一个MyListener.log文件中。名字属性指定了监听者的名字,类型指定了作者监听对象的类型,它必须是从System.Diagnostics.TraceListener派生下来的。只有在极少数情况下你才创建自己的监听类,那就是你觉得.Net框架的监听类不够用。initializeData的值是一个字符串,用于传给对象的构造函数。而TextWriterTraceListeners把它用于文件名。

你可以小做一个扩展,让它可以在应用中每个部署的程序集上都可以简单的使用。对于每个程序集,添加一个类来跟踪程序集创建的诊断:


internal class MyAssemblyDiagnostics
{
  static private TraceSwitch myAssemblySwitch =
    new TraceSwitch( "MyAssembly",
    "The switch for this assembly" );

  internal static void Msg( TraceLevel l, object o )
  {
    Trace.WriteLineIf( myAssemblySwitch.Level >= l,
      o, "MyAssembly" );
  }

  internal static void Msg( TraceLevel l, string s )
  {
    Trace.WriteLineIf( myAssemblySwitch.Level >= l,
      s, "MyAssembly" );
  }

  // Add additional output methods to suit.
}


MyAssemblyDiagnostices类根据一个开关来为这个程序集创建诊断信息。为了创建信息,调用按常规调用重载的Msg的任何一个就行了:


public void Method1( )
{
  MyAssemblyDiagnostics.Msg( TraceLevel.Info,
    "Entering Method1." );

  bool rVal = DoMoreWork( );

  if( rVal == false )
  {
    MyAssemblyDiagnostics.Msg( TraceLevel.Warning,
      "DoMoreWork Failed in Method1" );
  }

  MyAssemblyDiagnostics.Msg( TraceLevel.Info,
    "Exiting Method1." );
}

利用一个全局的开关,你还可以组件特殊的程序集开关,来控制整个应用程序的输出:


internal static void Msg( TraceLevel l, object o )
{
  Trace.WriteLineIf ( librarySwitch.Level >= l ||
    globalSwitch.Level >= l,
    o, "MyLibrary" );
}

internal static void Msg( TraceLevel l, string s )
{
  Trace.WriteLineIf( librarySwitch.Level >= l ||
    globalSwitch.Level >= l,
    s, "MyLibrary" );
}

这样,你就可以在应用程序上诊断信息,而且更友好的控制个别库文件的输出。在应用程序的任何地方,你都可以设置应用程序级的诊断到错误级,从而发现错误。当你有一个独立的问题时,你可以通过提高这个库的输出级别,从而精确的发现问题的源头。

在实际环境中,对于已经布署的应用程序,诊断库对于程序诊断和维护是必须的。但你自己不必写这些诊断库:.Net FCL已经完成了核心的功能。尽可能完全的使用它们,然后在满足特殊要求时扩展它们。这样,即使是在产品发布的环境中也可以捕获所有的问题。


关于 Exception


在一个产品的代码中(C++写的),发现了作者是调用COM的时候
一直用:
try
{}
catch(...)
{}

问其他同事为啥这么做?答曰:为了保证组件被调用的时候不崩溃

我崩溃,我感觉这其实是对Exception的使用不清楚地缘故。
如果不知道异常怎么处理,直接吞下异常有什么好处?还不如让程序崩溃呢


我的理解正确?达人指点下
-----------------------------------
from Shaking
直接吞异常,是不行的。
貌似我以前转载过三篇文章,关于这个。

------------------------------------
from Shaking
对于异常,除非你知道该怎么handle,recover,
才能catch下来。否则就不要catch,至少catch了要rethrow。

-----------------------------------
from Zip
John Robbins 在他的书中说过,永远不要使用 catch(...)



2008年12月22日星期一

用XML字符串作为参数的好处

   我在设计接口的时候,有函数的参数是某种各式的字符串

一开始用了自定义的某种格式的字符串,例如一个list用"a,b,c,d"来表示等等
甚至两组不同的list之间在用";"隔开。

因为这些COM接口是供VB调用的,所有有这样的接口

老板给我指出这是很不好的习惯

因为一旦格式有所改变,可能你修改代码的地方会比较多
而用XML+LINQ会比较方便,XML加些内容,原有的代码也基本不用改变






LINQ and XML

1, 从集合中选择出符合条件的子集合

var _f = from q in _fields

         where (0 == string.Compare(q.Name, strFieldName, true))

         select q;

if (0 == _f.Count())

          throw new ArgumentException(Resource.FieldNotExist);

return _f.ElementAt(0);


2,将一个过滤后的集合转换成Dictionary

var _fStrings = from q in _field.FormattedStrings

                select new { q.Value, q.Key };

var _dict = _fStrings.ToDictionary(e => e.Value.ToUpper(), e => e.Key);



3XML字符串初始化,得到一个集合

XElement _xmlTagNames = XElement.Load(XmlReader.Create(new StringReader(strTagNames)));

var _tNames = from q in _xmlTagNames.Descendants(Resource.Tag)

              select q.Value;

4,将集合保存为一个XML文件

XElement _xml = new XElement(Resource.DefinitionRecords,

new XAttribute(Resource.ServerName, m_access.Server),

from key in _definitions.Keys

select new XElement(Resource.Definition, new XAttribute(Resource.Name, key), from f in _definitions[key]

where (f.RepeatArea == 0)

select new XElement(Resource.Field, new XAttribute(Resource.Name, f.Name), new XAttribute(Resource.DataType, FieldDataTypeMgr.GetDataTypeById(f.DataType).ToString()),

                                                                             new XAttribute(Resource.IsReadonlyUsable, f.ReadOnlyUsable.ToString()),

                                                                             new XAttribute(Resource.IsReadonlyUnusable,f.ReadOnlyUnusable.ToString()),

from e in f.FormattedStrings.Keys

select new XElement(Resource.Enum, new XAttribute(Resource.EnumValue, e.ToString()),

new XAttribute(Resource.DisplayValue, f.FormattedStrings[e].Trim()))

)));

XDocument _xdoc = new XDocument(_xml);

_xdoc.Save(path);


5,将集合转化成一个XML字符串

XElement _xmlTagValues = new XElement(…);

xmlTagValues.ToString()



http://odetocode.com/Articles/739.aspx

http://odetocode.com/Articles/738.aspx

http://odetocode.com/Articles/737.aspx


This e-mail and any attachments are intended only for use by the addressee(s) named herein and may contain legally privileged and/or confidential information. If you are not the intended recipient of this e-mail, you are hereby notified any dissemination, distribution or copying of this email, and any attachments thereto, is strictly prohibited. If you receive this email in error please immediately notify the sender and permanently delete the original copy and any copy of any e-mail, and any printout thereof.

COM Interop--用C#创建COM组件

COM Interop

 

如果你想用C#COM组件,那么你需要用COM interop.

 

1,创建COM接口

 

[ Guid("B5F89E59-B5F9-43a9-94E0-DC05A178A23E") ]

[ InterfaceType(ComInterfaceType.InterfaceIsDual) ]

[ ComVisible(true) ]

Interface IMyFunction

{

   Void Func1();

}

 

 

2,创建实现

 

[ Guid("FB060B69-5B1F-419b-BCEB-BAD9083CAE40")]

[ ClassInterface(ClassInterfaceType.None)]

[ ComSourceInterfaces(typeof(IMyFunction))]

[ ProgId("MyAssembly.FunctionImp")]

[ ComVisible( true ) ]

public class FunctionImp : IMyFunction

{

}

 

3,修改项目设置

 

Build设置中设置注册

 

4,如果在别的机器上使用需要手动注册

regasm  /codebase  MyAssembly.dll   /tlb: MyAssembly.tlb /register

 

或者安装在gac中,然后用gacutil注册

 

5,问题

有时候在本机gac中,安装完后你无法调试,那么你需要将最新的ASSEMBLY重新安装到gac中,然后就可以调试了

 

不要在项目级别设置ComVisible,只暴露需要暴露的接口和实现类

Effective C#学习系列-- Item31 使用小而简单的函数

 ITEM31. 使用小而简单的函数

不要写很长很复杂的函数来避免过多的函数调用带来的开销,在C#中不会如你所想象的那样起作用。因为JIT是即时一个函数一个函数的编译的,没有被用到的函数是不会被编译的,所以函数过长会导致没有用到的分支被编译。

 

另外小的简单的函数,一般局部变量比较少,容易被JIT放入到寄存器中以优化

 

2008年12月12日星期五

今天终于有了自己的博客了

哈哈