<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mingbo &#187; myNote</title>
	<atom:link href="http://shao.mingbo.de/tag/%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0/feed/" rel="self" type="application/rss+xml" />
	<link>http://shao.mingbo.de</link>
	<description>包括教育技术，编程，互联网等方面的文章及随想。</description>
	<lastBuildDate>Sun, 25 Jul 2010 05:18:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>cSharp中BackgroundWorker的用法</title>
		<link>http://shao.mingbo.de/2009/12/22/how-to-use-backgroundworker-in-csharp/</link>
		<comments>http://shao.mingbo.de/2009/12/22/how-to-use-backgroundworker-in-csharp/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 01:17:27 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[BackgroundWorker]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[同步]]></category>
		<category><![CDATA[线程]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=412</guid>
		<description><![CDATA[线程同步中，还有一个比较流行的类&#60;BackgroundWorker&#62;.
BackgroundWorker 类允许您在单独的专用线程上运行操作。耗时的操作（如下载和数据库事务）在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面，而且面临与这类操作相关的长时间延迟，则可以使用 BackgroundWorker 类方便地解决问题。
若要在后台执行耗时的操作，请创建一个 BackgroundWorker，侦听那些报告操作进度并在操作完成时发出信号的事件。可以通过编程方式创建BackgroundWorker，也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 BackgroundWorker，则它会出现在组件栏中，而且它的属性会显示在“属性”窗口中。
若要设置后台操作，请为 DoWork 事件添加一个事件处理程序。在此事件处理程序中调用耗时的操作。若要启动该操作，请调用 RunWorkerAsync。若要收到进度更新通知，请对 ProgressChanged 事件进行处理。若要在操作完成时收到通知，请对 RunWorkerCompleted 事件进行处理。
下面这个例子，主要从这几个方面来谈 cancellation support and report progress。
    public partial class Form1 : Form
    {

        public Form1()
        {
           [...]]]></description>
			<content:encoded><![CDATA[<p>线程同步中，还有一个比较流行的类&lt;<strong>BackgroundWorker</strong>&gt;.</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;"><strong>BackgroundWorker</strong> 类允许您在单独的专用线程上运行操作。耗时的操作（如下载和数据库事务）在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面，而且面临与这类操作相关的长时间延迟，则可以使用 <strong>BackgroundWorker</strong> 类方便地解决问题。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">若要在后台执行耗时的操作，请创建一个 <strong>BackgroundWorker</strong>，侦听那些报告操作进度并在操作完成时发出信号的事件。可以通过编程方式创建<strong>BackgroundWorker</strong>，也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 <strong>BackgroundWorker</strong>，则它会出现在组件栏中，而且它的属性会显示在“属性”窗口中。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">若要设置后台操作，请为 DoWork 事件添加一个事件处理程序。在此事件处理程序中调用耗时的操作。若要启动该操作，请调用 RunWorkerAsync。若要收到进度更新通知，请对 ProgressChanged 事件进行处理。若要在操作完成时收到通知，请对 RunWorkerCompleted 事件进行处理。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">下面这个例子，主要从这几个方面来谈 <strong>cancellation support</strong> and <strong>report progress</strong>。</p>
<pre name="code" class="c-sharp">    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
            this.backgroundWorker1.WorkerSupportsCancellation = true;
            this.backgroundWorker1.WorkerReportsProgress = true;

            this.backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.textBox1.Text != "" &amp;&amp; this.textBox2.Text != "")
            {
                ab a = new ab(int.Parse(this.textBox1.Text), int.Parse(this.textBox2.Text));
                this.backgroundWorker1.RunWorkerAsync(a);
            }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.backgroundWorker1.CancelAsync();
        }

        void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }

        void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                this.textBox3.Text = "Result :Canclled!";
                this.progressBar1.Value = 100;
            }
            else if (e.Error != null)
            {
                MessageBox.Show("Error Details : " + (e.Error as Exception).ToString());
            }
            else
            {
                    this.textBox3.Text = "Result :" + e.Result;
                    this.progressBar1.Value = 100;
             }
        }

        void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            //do something here backgroundly.

                for (int i = 0; i &lt; this.progressBar1.Maximum; i++)
                {
                    Thread.Sleep(50);
                    this.backgroundWorker1.ReportProgress(i);

                    if (this.backgroundWorker1.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                }
                ab a = (ab)e.Argument;
                e.Result = a.C;

            }

    }

    class ab
    {
        private int _a;

        public int A
        {
            get { return _a; }
            set { _a = value; }
        }
        private int _b;

        public int B
        {
            get { return _b; }
            set { _b = value; }
        }
        public ab(int a,int b)
        {
            this._a = a;
            this._b = b;
        }

        public int C
        {
            get { return _b + _a; }
        }
    }</pre>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/12/22/how-to-use-backgroundworker-in-csharp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cSharp中同步类的设计</title>
		<link>http://shao.mingbo.de/2009/12/21/synchronize-class-design-in-csharp/</link>
		<comments>http://shao.mingbo.de/2009/12/21/synchronize-class-design-in-csharp/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 01:42:31 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[同步]]></category>
		<category><![CDATA[线程]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=408</guid>
		<description><![CDATA[尽量的避免问题，我们最好不要在线程之间共享数据。如果要共享数据，就必须使用同步技术：确保一次只有一个线程访问和改变共享数据。其中不可避免的要用到“锁”。使用锁是需要时间的，并且，也不是总是必须的。所以对于一个类，我们可以创建一个类的2个版本，一个同步版本，一个异步版本。下面请看这个例子：
        public class SynDemo
        {
            public virtual bool IsSynchronized
            {
          [...]]]></description>
			<content:encoded><![CDATA[<p>尽量的避免问题，我们最好不要在线程之间共享数据。如果要共享数据，就必须使用同步技术：确保一次只有一个线程访问和改变共享数据。其中不可避免的要用到“锁”。使用锁是需要时间的，并且，也不是总是必须的。所以对于一个类，我们可以创建一个类的2个版本，一个同步版本，一个异步版本。下面请看这个例子：</p>
<pre name="code" class="c-sharp">        public class SynDemo
        {
            public virtual bool IsSynchronized
            {
                get { return false; }
            }

            public virtual void doThis()
            {
                //dothis
            }

            public virtual void doThat()
            {
                //doThat
            }

            public static SynDemo SynchronizeDemo(SynDemo d)
            {
                if (!d.IsSynchronized)
                {
                    return new SynchronizedDemo(d);
                }
                return d;
            }

                    private class SynchronizedDemo : SynDemo
                    {
                        private SynDemo _demo;
                        private object _synRoot =new object();

                        public SynchronizedDemo(SynDemo d)
                        {
                            this._demo = d;
                        }

                        public override bool IsSynchronized
                        {
                            get
                            {
                                return true;
                            }
                        }

                        public override void doThat()
                        {
                            lock(_synRoot)
                            {
                                _demo.doThat();
                            }
                        }

                        public override void doThis()
                        {
                            lock(_synRoot)
                            {
                                _demo.doThis();
                            }
                        }

                    }
        }</pre>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/12/21/synchronize-class-design-in-csharp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cSharp中给线程传递参数</title>
		<link>http://shao.mingbo.de/2009/12/20/paralize-thread-in-charp/</link>
		<comments>http://shao.mingbo.de/2009/12/20/paralize-thread-in-charp/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 03:13:38 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[线程]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=405</guid>
		<description><![CDATA[在c#中如何给线程传递参数呢？其实很简单。一般来说可以采用2种方式：

使用带parameterizeThreadStart委托参数的Thread构造函数
定制一个类，通过该类的构造函数初始化想要传递的参数，再将该参数应用该类的方法。把线程的方法定义为该类实例的方法即可。

下面是一个Demo ：
        public static void Main()
        {
            //1.使用一个带参数的委托ParameterizedThreadStart来初始化Thread
            myData data = new myData();
       [...]]]></description>
			<content:encoded><![CDATA[<p>在c#中如何给线程传递参数呢？其实很简单。一般来说可以采用2种方式：</p>
<ul>
<li>使用带parameterizeThreadStart委托参数的Thread构造函数</li>
<li>定制一个类，通过该类的构造函数初始化想要传递的参数，再将该参数应用该类的方法。把线程的方法定义为该类实例的方法即可。</li>
</ul>
<p>下面是一个Demo ：</p>
<pre name="code" class="c-sharp">        public static void Main()
        {
            //1.使用一个带参数的委托ParameterizedThreadStart来初始化Thread
            myData data = new myData();
            data.Message = "new Info";
            new Thread(paralizeThread).Start(data);
            //2.通过初始化一个类的字段，将该类的方法封装到线程中去
            new Thread(new myThreadClass("new info2").ThreadMethod).Start();

        }
        //类或结构都行
        struct myData
        {
            string message;

            public string Message
            {
                get { return message; }
                set { message = value; }
            }
        }

        static void paralizeThread(object o)
        {
            myData data = (myData)o;
            Console.WriteLine("Thread {1} received a Parameter : {0}",data.Message,Thread.CurrentThread.ManagedThreadId);
        }

        class myThreadClass
        {
            string _message;
            public myThreadClass(string message)
            {
                this._message = message;
            }

            public void ThreadMethod()
            {
                Console.WriteLine("Thread {1} received a Parameter : {0}", this._message, Thread.CurrentThread.ManagedThreadId);
            }
        }</pre>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/12/20/paralize-thread-in-charp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cSharp中异步委托的笔记</title>
		<link>http://shao.mingbo.de/2009/12/19/asynchronous-delegate-in-csharp/</link>
		<comments>http://shao.mingbo.de/2009/12/19/asynchronous-delegate-in-csharp/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 12:13:33 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[委托]]></category>
		<category><![CDATA[异步]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=392</guid>
		<description><![CDATA[异步委托，首先要搞明白，为什么要用到异步委托。
长时间以来，我个人在编写代码的时候，都认为程序应该是执行完一件事之后，然后再干接下来的。这用计算机术语来讲，叫同步执行（Synchronous Execution）。但事实上，这样的执行效果不一定人性化。举下面的一组对照：

你有3份快件需要传递给远程客户。如果这件事由你本人亲自完成，那么，接下来，你将要停下手中的工作，跑3段路程，分别将这3个快件递交给3个不同的客户。然后返回公司继续执行你手上剩下的工作。现实生活中，这样的事情或许永远不会发生，因为聪明的你会打一个电话叫来快递专员来为你解决快件问题。
刚入学那会，写了一个资源转换工具。那个时候还没意识到出现了这样的问题：当我执行转换的时候，UI 无法继续响应用户的操作，而只有当转换完毕之后才恢复正常。实际上，现在分析起来，就是主线程没空搭理你，它正忙，忙完之后才能执行你的更新的操作。这个处境和之前的那个跑3段路传递3个快件的境遇差不多。.net 为我们设计了这个异步委托来执行类似快递专员的工作。

搞懂异步委托，需要理解BeginInvoke() ,EndInvoke() ,IAsyncResult 以及AsyncCallback 委托:
异步委托提供以异步方式调用同步方法的能力。当同步调用一个委托时，“Invoke”方法直接对当前线程调用目标方法。如果编译器支持异步委托，则它将生成“Invoke”方法以及“BeginInvoke”和“EndInvoke”方法。如果调用“BeginInvoke”方法，则公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行，该目标方法是对线程池线程运行的。如果在对“BeginInvoke”方法的调用中指定了回调方法，则当目标方法返回时将调用该回调方法。在回调方法中，“EndInvoke” 方法获取返回值和所有输入/输出参数。如果在调用“BeginInvoke”时未指定任何回调方法，则可以从调用“BeginInvoke”的线程中调用“EndInvoke”。
下面，我用一个例子，谈谈可能发生的4种情况
    class Programe
    {
        private delegate void ADelegateSomewhat(int x);

        public static void Main()
        {
     [...]]]></description>
			<content:encoded><![CDATA[<p>异步委托，首先要搞明白，为什么要用到异步委托。</p>
<p>长时间以来，我个人在编写代码的时候，都认为程序应该是执行完一件事之后，然后再干接下来的。这用计算机术语来讲，叫同步执行（Synchronous Execution）。但事实上，这样的执行效果不一定人性化。举下面的一组对照：</p>
<ul>
<li>你有3份快件需要传递给远程客户。如果这件事由你本人亲自完成，那么，接下来，你将要停下手中的工作，跑3段路程，分别将这3个快件递交给3个不同的客户。然后返回公司继续执行你手上剩下的工作。现实生活中，这样的事情或许永远不会发生，因为聪明的你会打一个电话叫来快递专员来为你解决快件问题。</li>
<li>刚入学那会，写了一个<a href="http://shao.mingbo.de/2009/10/10/ipv6-web-auto-adaptation/">资源转换工具</a>。那个时候还没意识到出现了这样的问题：当我执行转换的时候，UI 无法继续响应用户的操作，而只有当转换完毕之后才恢复正常。实际上，现在分析起来，就是主线程没空搭理你，它正忙，忙完之后才能执行你的更新的操作。这个处境和之前的那个跑3段路传递3个快件的境遇差不多。.net 为我们设计了这个<strong>异步委托</strong>来执行类似快递专员的工作。</li>
</ul>
<p>搞懂<strong>异步委托</strong>，需要理解<strong>BeginInvoke() </strong>,<strong>EndInvoke()</strong> ,<strong>IAsyncResult</strong> 以及<strong>AsyncCallback</strong> 委托:</p>
<blockquote><p>异步委托提供以异步方式调用同步方法的能力。当同步调用一个委托时，“Invoke”方法直接对当前线程调用目标方法。如果编译器支持异步委托，则它将生成“Invoke”方法以及“BeginInvoke”和“EndInvoke”方法。如果调用“BeginInvoke”方法，则公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行，该目标方法是对线程池线程运行的。如果在对“BeginInvoke”方法的调用中指定了回调方法，则当目标方法返回时将调用该回调方法。在回调方法中，“EndInvoke”<strong> </strong>方法获取返回值和所有输入/输出参数。如果在调用“BeginInvoke”时未指定任何回调方法，则可以从调用“BeginInvoke”的线程中调用“EndInvoke”。</p></blockquote>
<p>下面，我用一个例子，谈谈可能发生的4种情况</p>
<pre name="code" class="c-sharp">    class Programe
    {
        private delegate void ADelegateSomewhat(int x);

        public static void Main()
        {
            ADelegateSomewhat aD = MathPupil;
            ////1.直接调用EndInvoke,这和直接调用MathPupil(100)的效果一样，
            ////但会等到这个方法执行完之后才去执行后面的语句
            //IAsyncResult ar= aD.BeginInvoke(100,null,null);
            //aD.EndInvoke(ar);

            ////2.轮询,每隔50毫秒看看孩子算完了没.
            //IAsyncResult ar = aD.BeginInvoke(200, null, null);
            //while (!ar.IsCompleted)
            //{
            //    Console.Write(".");
            //    Thread.Sleep(500);
            //}
            //aD.EndInvoke(ar);

            ////3.实际上和2的方法类似，只是把Sleep的时间放上来了
            ////但事实上，功能会多点,比如控制跳出的条件等
            //IAsyncResult ar = aD.BeginInvoke(300,null,null);
            //while (!ar.AsyncWaitHandle.WaitOne(500))
            //{
            //    Console.Write(".");
            //}
            //aD.EndInvoke(ar);

            //4.回调函数,最有意义,设置相对麻烦点
            IAsyncResult ar = aD.BeginInvoke(400, MathCallBack, aD);
            //现在干点别的事，不用关心算算术题的孩子了。
            //由delegate的回调方法自动来管理
            Console.ReadLine();
            //如果不等待委托完成其任务就结束主线程，委托线程就会停止
        }

        //假装自己一个小学生处理一道加法算术题，历时5秒钟
        static void MathPupil(int x)
        {
            Console.WriteLine("Now I'll pretend to be a pupil");
            int sum = 0;
            for (int i = 0; i &lt; x; i++)
            {
                sum += i;
                Thread.Sleep(5000/x);
            }
            Console.WriteLine("After 5 secends, i've got the answer :" +sum);
        }

        static void MathCallBack(IAsyncResult ar)
        {
            ADelegateSomewhat aD = (ADelegateSomewhat)ar.AsyncState;
            aD.EndInvoke(ar);
        }

    }</pre>
<p>我想，到目前为止，应该收回<a href="http://shao.mingbo.de/2009/12/02/customize-event-in-csharp/">之前提到委托</a>“从来不是一个重点”的言论了。</p>
<p>参考资料：<a href="http://msdn.microsoft.com/en-us/magazine/cc164036.aspx" target="_blank">&lt;MSDN-magazine&gt;:Asynchronous Method Execution Using Delegates</a></p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/12/19/asynchronous-delegate-in-csharp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cSharp动态调用和反射的一个绝佳例子</title>
		<link>http://shao.mingbo.de/2009/12/16/dynamic-loading-assemblies-and-reflection-in-csharp/</link>
		<comments>http://shao.mingbo.de/2009/12/16/dynamic-loading-assemblies-and-reflection-in-csharp/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 15:28:22 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[动态调用]]></category>
		<category><![CDATA[反射]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=377</guid>
		<description><![CDATA[之前看反射那一章，真把个人看郁闷了。不巧的是，看到很多业内人士的专业博客说，不会这个也搞了几年的项目开发。哎。顿时打消了学习这个知识的念头。不过，挺巧的是，今天又遇到了一个讲这个内容的章节，只不过内容更具体了。
这样一个动态调用的程序，貌似实现了一个编译器的功能。在Textbox里写上代码，能在程序下方看到编译结果。有趣的是，当代码出错的时候，能在程序中看到错误信息：


//核心代码
       public string ComplieAndRun(string input,out bool hasError)
        {
            CompilerResults cResults = null;
            string returnData = null;
     [...]]]></description>
			<content:encoded><![CDATA[<p>之前看反射那一章，真把个人看郁闷了。不巧的是，看到很多业内人士的专业博客说，不会这个也搞了几年的项目开发。哎。顿时打消了学习这个知识的念头。不过，挺巧的是，今天又遇到了一个讲这个内容的章节，只不过内容更具体了。</p>
<p>这样一个动态调用的程序，貌似实现了一个编译器的功能。在Textbox里写上代码，能在程序下方看到编译结果。有趣的是，当代码出错的时候，能在程序中看到错误信息：</p>
<p style="text-align: center;"><a href="http://shao.mingbo.de/wp-content/uploads/2009/12/dynamic-loading-assemblies.jpg"><img class="aligncenter size-full wp-image-383" title="dynamic-loading-assemblies" src="http://shao.mingbo.de/wp-content/uploads/2009/12/dynamic-loading-assemblies.jpg" alt="dynamic loading assemblies cSharp动态调用和反射的一个绝佳例子" width="455" height="315" /></a></p>
<pre name="code" class="c-sharp">
//核心代码
       public string ComplieAndRun(string input,out bool hasError)
        {
            CompilerResults cResults = null;
            string returnData = null;
            hasError = false;

            using(Microsoft.CSharp.CSharpCodeProvider provider =new CSharpCodeProvider())
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(prefix);
                sb.Append(input);
                sb.Append(postfix);

                CompilerParameters option = new CompilerParameters();
                option.GenerateInMemory = true;
                cResults=provider.CompileAssemblyFromSource(option, sb.ToString());

            }

            if (cResults.Errors.HasErrors)
            {
                hasError = true;
                StringBuilder errMessage = new StringBuilder();
                foreach (CompilerError err in cResults.Errors)
                {
                    errMessage.AppendFormat("{0}:{1}", err.Line, err.ErrorText);
                }
                returnData = errMessage.ToString();
            }
            else
            {
                TextWriter temp=Console.Out;
                StringWriter sw = new StringWriter();
                Console.SetOut(sw);

                Type myType = cResults.CompiledAssembly.GetType("myDriver");
                myType.InvokeMember("Run", BindingFlags.InvokeMethod|BindingFlags.Public | BindingFlags.Static, null, null, null);

                Console.SetOut(temp);

                returnData = sw.ToString();
            }

            return returnData;
        }
    }

    //每次动态调用后，通过应用程序域卸载掉
    public class DynamicRunAppInDomain
    {
        public string CompileAndRun(string input,out bool hasErr)
        {
            AppDomain app = AppDomain.CreateDomain("DynamicRun");
            DynamicRun dr = (DynamicRun)app.CreateInstanceAndUnwrap("ShaoMingboDrive", "WpfApplication1.DynamicRun");
            string res = dr.ComplieAndRun(input,out hasErr);
            AppDomain.Unload(app);
            return res;

        }
    }</pre>
<p>这里是一个该程序的二进制文件：<a class="downloadlink" href="http://shao.mingbo.de/wp-content/plugins/download-monitor/download.php?id=4" title="Version1.0 downloaded 55 times" >动态调用demo (55)</a><strong>.net framework 3.5 required</strong><br />
如果您的机器上没有安装.net，不妨下载这个打包好的文件：<a class="downloadlink" href="http://shao.mingbo.de/wp-content/plugins/download-monitor/download.php?id=5" title=" downloaded 56 times" >动态调用Setup (56)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/12/16/dynamic-loading-assemblies-and-reflection-in-csharp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cSharp中异常处理的笔记</title>
		<link>http://shao.mingbo.de/2009/12/12/exception-handle-in-csharp/</link>
		<comments>http://shao.mingbo.de/2009/12/12/exception-handle-in-csharp/#comments</comments>
		<pubDate>Sat, 12 Dec 2009 11:00:09 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[异常处理]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=359</guid>
		<description><![CDATA[停了几天的笔记。感觉学习的内容要么像反射（Reflection in .net framework）一样高深，想写点笔记却怎么也写不上；要么学习的内容（像集合、泛型，泛型集合、Language Integrated Querry）太细太杂，可写的太多，想记都记不过来。看到了.net 中的异常处理，总算，让我开始有点想法了。我总结了下面的几个问题：
1.执行多个catch 块，讲究一个顺序：从最特殊到最一般。下面的代码是我写的一个demo，模拟了3种异常：一种是用户的输入超过了规定值后，抛出了一个IndexOutOfRangeException，另一种是很普适的System.Exception，最后一种是不带参数的catch，它可以处理非托管堆上的代码异常（包括非c# 的代码）。以这样的顺序布局，才能够细致的捕获到各个可能出现的问题。但，如果将System.Exception 的catch 放到最前面，编译器就会报错：“上一个 catch 子句已经捕获了此类型或超类型(“System.Exception”)的所有异常”，因为IndexOutOfRangeException是从System.Exception 里继承过来的。当然要体会这样布局的真正优势，需要一些彪悍的异常处理方法，而不是一个简单的Writeline().
错误 1 上一个 catch 子句已经捕获了此类型或超类型(“System.Exception”)的所有异常 H:\vsProject\Lab\learningLab\learningLab\Programe.cs 28 20 learningLab
        public static void Main()
        {
            int aNum;
  [...]]]></description>
			<content:encoded><![CDATA[<p>停了几天的笔记。感觉学习的内容要么像反射（Reflection in .net framework）一样高深，想写点笔记却怎么也写不上；要么学习的内容（像集合、泛型，泛型集合、Language Integrated Querry）太细太杂，可写的太多，想记都记不过来。看到了.net 中的异常处理，总算，让我开始有点想法了。我总结了下面的几个问题：</p>
<p><strong>1.执行多个catch 块，讲究一个顺序：<span style="text-decoration: underline;"><span style="color: #ff0000;">从最特殊到最一般</span></span>。</strong>下面的代码是我写的一个demo，模拟了3种异常：一种是用户的输入超过了规定值后，抛出了一个IndexOutOfRangeException，另一种是很普适的System.Exception，最后一种是不带参数的catch，它可以处理非托管堆上的代码异常（包括非c# 的代码）。以这样的顺序布局，才能够细致的捕获到各个可能出现的问题。但，如果将System.Exception 的catch 放到最前面，编译器就会报错：“<span style="text-decoration: underline;">上一个 catch 子句已经捕获了此类型或超类型(“System.Exception”)的所有异常</span>”，因为IndexOutOfRangeException是从System.Exception 里继承过来的。当然要体会这样布局的真正优势，需要一些彪悍的异常处理方法，而不是一个简单的Writeline().</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 28px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">错误 1 上一个 catch 子句已经捕获了此类型或超类型(“System.Exception”)的所有异常 H:\vsProject\Lab\learningLab\learningLab\Programe.cs 28 20 learningLab</div>
<pre name="code" class="c-sharp">        public static void Main()
        {
            int aNum;
            Console.WriteLine("Input a number between 1 and 5:");
            string userInput = Console.ReadLine();
            try
            {
                aNum = Int32.Parse(userInput);
                if (aNum<1 || aNum> 5)
                    throw new System.IndexOutOfRangeException("You type :" + userInput);
            }
            catch (IndexOutOfRangeException e)
            {
                Console.WriteLine("Number should be between 1 and 5. But " + e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("An Exception in Managed Heap thrown by .net framework :" + e.Message);
            }
            catch
            {
                Console.WriteLine("An Exception in Unmanaged heap thrown by the .net framework!");
            }
            finally {
                Console.WriteLine("Thank you!");
            }

        }
    }</pre>
<p>另外，这个代码在编译的时候会有一个警告：&#8221;上一个 catch 子句已捕获所有异常。引发的所有非异常均被包装在 System.Runtime.CompilerServices.RuntimeWrappedException 中。 &#8220;这个是因为本代码中根本就不包含非c# 的代码，出现的异常都在托管堆中发生。事实上这个代码的工作频率并不大，这里写上只是为了说明这个规则。</p>
<p><strong>2.修改异常类型。</strong>在上面的demo 中，如果用户没有输入一个数字而是字母或者是数字和字母的组合，那么将会看到：&#8221;<span style="text-decoration: underline;">An Exception in Managed Heap thrown by .net framework :输入字符串的格式不正确。</span>&#8220;我们知道错误是发生在Int32.Parse()这个方法里。但Exception 给出的提示信息不太符合咱们的思维，并且从安全的角度来说，它甚至有可能暴露程序的某些底层问题。因此修改异常类型迫在眉睫！</p>
<p><strong>3.设计异常中间类型</strong>。一段代码，可能异常处理集中在一堆里，但细节各不相同。为了使得整体的规律性，以及代码的便于管理，可以在这里给出一个继承于System.ApplicationException 的中间类，如MethodException。细致的处理异常，可以继续继承于MethodException，如OutOfRangeInMethodException,NotSupportMethodException等来处理各种不同的异常，这样就解决了第2点中提到的问题。</p>
<p><strong>4.嵌套的try-catch块</strong>。我想还是代码最能说明问题:</p>
<pre name="code" class="c-sharp">            try {
                    //point A
                try
                {
                    //point B
                }
                catch {
                    //point C
                }
                finally {
                    //point D
                }

            }
            catch {
                    //Error hanling
            }
            finally {
                    //clean up
            }</pre>
<p>这里没有处理什么问题，只是将2个嵌套的try-catch 块进行了一个大致的区域划分。</p>
<ul>
<li>当异常在point A、或者point D 中爆发，问题很简单，将由外层的catch 来捕获；</li>
<li>当异常在point A、或者point D 中爆发，而问题不太简单的时候，外层catch 无法捕获时，由.net framework 的隐藏try-catch 来捕获。</li>
<li>当异常在point B 中爆发，问题很简单，将由内层catch 来捕获；</li>
<li>当异常在point B 中爆发，而问题不太简单的时候，跳出内层try-catch 块，执行内层finally 块，问题变为在point A或者point D 爆发异常。</li>
<li>当异常在point C 中爆发，则会执行爆发C 异常之前的处理B的代码，而后退出内层try-catch 块，执行内层finally 块，问题变为在point A或者point D 爆发异常。</li>
</ul>
<p>多少个try-catch 都不是问题，这个例子只说明了嵌套try-catch 块的工作方式。开水房要关门了，我去打水先&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/12/12/exception-handle-in-csharp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>cSharp中委托和事件的学习笔记</title>
		<link>http://shao.mingbo.de/2009/12/02/customize-event-in-csharp/</link>
		<comments>http://shao.mingbo.de/2009/12/02/customize-event-in-csharp/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 10:03:33 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[事件]]></category>
		<category><![CDATA[委托]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=343</guid>
		<description><![CDATA[运算符重载那一章的内容，等整理完了再稍后奉上。首先，让我趁热打铁的把委托和事件的笔记写完。不得不说，看到这里，觉得《Professional C#2008》这本书写的够烂的了。一个排序比较的例子，从接口那一章用到了委托，实在有点牵强，虽然一个比较算法用委托来定义是有效的，但把一个比较的能力看做是一个对象所拥有的属性更为恰当。当然，作者这样安排书的内容，无疑让我们可以看到：接口和委托都是允许类设计器分离声明和实现的。那么什么时候该用委托，什么时候该用接口呢？下面给出微软的一些我觉得还不错的建议。
以下几种情况比较适合委托：

当使用事件设计模式时；
当封装静态方式调用时；
当需要一个方法的多个实现时；（多播委托）
当调用一个实例方法而它不需要使用该实例的其他属性，方法，字段时；（独立性）

以下情况比较适合接口：

当方法和类型的能力挂钩时；（如类的自我比较能力IComparable）
当有一组可能被调用的相关方法时；（它们可能参数类型各不相同）
当类只需要方法的单个实现时；

委托从来不是一个重点，但委托，总是和事件联系紧密，再提到事件之前，必须要对他进行一个小小的知识梳理和补充。
委托：

委托实现了类似于c++ 中的函数指针，它包含的只是方法的地址，它可以将方法作为参数进行传递，它很安全
委托在c#2.0中使用了委托推断（允许不用new了），实现了匿名方法，在c#3.0中加入了Lambda 表达式，利用它们可以更简练地编写内联代码块
多播委托，其签名必须返回为void，否则就只能得到最后一个方法的结果
多播委托中，一个方法抛出异常，整个迭代会被终止；使用GetInvocationList()，来进行手动迭代
协变是允许方法的返回类型为派生类；抗变是运行方法的参数类型为派生类

谈完了委托，现在该来说说我们关心的事件。

事件的发行者决定什么时候引发事件，而订户决定怎么来响应事件；
一个事件可以有多个订户，一个订户可以响应多个事件；
一个事件可以引发多个订户同时响应，事件可以同步线程（当然也可以异步调用）；
没有订户的事件永远不会发生

在编写代码的过程中，实现一个事件，会遇到下面的几个层次：

订阅和取消
实现符合.net Framework 标准的事件(EventHandler&#38; EventArgs)
实现继承关系中的事件设计
实现接口关系中的事件设计
在字典中实现事件的设计（暂未接触字典方面的知识）

下面，我想给出一个自己写的继承关系中的事件设计demo：

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace learningLab
{
    class growUPEventArgs:EventArgs
    {
        public string Message {get;set;}
        public growUPEventArgs(string message)
        {
      [...]]]></description>
			<content:encoded><![CDATA[<p>运算符重载那一章的内容，等整理完了再稍后奉上。首先，让我趁热打铁的把<strong>委托和事件</strong>的笔记写完。不得不说，看到这里，觉得《Professional C#2008》这本书写的够烂的了。一个排序比较的例子，从接口那一章用到了委托，实在有点牵强，虽然一个比较算法用委托来定义是有效的，但把一个比较的能力看做是一个对象所拥有的属性更为恰当。当然，作者这样安排书的内容，无疑让我们可以看到：接口和委托都是允许类设计器分离声明和实现的。那么什么时候该用委托，什么时候该用接口呢？下面给出微软的一些我觉得还不错的建议。</p>
<p>以下几种情况比较适合<strong>委托</strong>：</p>
<ol>
<li>当使用事件设计模式时；</li>
<li>当封装静态方式调用时；</li>
<li>当需要一个方法的多个实现时；（多播委托）</li>
<li>当调用一个实例方法而它不需要使用该实例的其他属性，方法，字段时；（独立性）</li>
</ol>
<p>以下情况比较适合接口：</p>
<ol>
<li>当方法和类型的能力挂钩时；（如类的自我比较能力IComparable）</li>
<li>当有一组可能被调用的相关方法时；（它们可能参数类型各不相同）</li>
<li>当类只需要方法的单个实现时；</li>
</ol>
<p>委托从来不是一个重点，但委托，总是和事件联系紧密，再提到事件之前，必须要对他进行一个小小的知识梳理和补充。</p>
<p>委托：</p>
<ul>
<li>委托实现了类似于c++ 中的函数指针，它包含的只是方法的地址，它可以将方法作为参数进行传递，它很安全</li>
<li>委托在c#2.0中使用了委托推断（允许不用new了），实现了匿名方法，在c#3.0中加入了Lambda 表达式，利用它们可以更简练地编写内联代码块</li>
<li>多播委托，其签名必须返回为void，否则就只能得到最后一个方法的结果</li>
<li>多播委托中，一个方法抛出异常，整个迭代会被终止；使用GetInvocationList()，来进行手动迭代</li>
<li>协变是允许方法的返回类型为派生类；抗变是运行方法的参数类型为派生类</li>
</ul>
<p>谈完了委托，现在该来说说我们关心的事件。</p>
<ul>
<li>事件的发行者决定什么时候引发事件，而订户决定怎么来响应事件；</li>
<li>一个事件可以有多个订户，一个订户可以响应多个事件；</li>
<li>一个事件可以引发多个订户同时响应，事件可以同步线程（当然也可以异步调用）；</li>
<li>没有订户的事件永远不会发生</li>
</ul>
<p>在编写代码的过程中，实现一个事件，会遇到下面的几个层次：</p>
<ul>
<li>订阅和取消</li>
<li>实现符合.net Framework 标准的事件(EventHandler&amp; EventArgs)</li>
<li>实现继承关系中的事件设计</li>
<li>实现接口关系中的事件设计</li>
<li>在字典中实现事件的设计（暂未接触字典方面的知识）</li>
</ul>
<p>下面，我想给出一个自己写的继承关系中的事件设计demo：</p>
<pre name="code" class="c-sharp">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace learningLab
{
    class growUPEventArgs:EventArgs
    {
        public string Message {get;set;}
        public growUPEventArgs(string message)
        {
            this.Message=message;
        }
    }

    abstract class person
    {
        private string _name;
        private int _age;

        public string Name
        {
            get
            {
                return _name;
            }
        }

        public int Age
        {
            get
            {
                return _age;
            }
        }

        public person(string name,int age)
        {
            this._age = age;
            this._name = name;

        }

        //这里并没有使用委托而是使用了泛型的EventHandler，可以节约一行代码
        public event EventHandler<growUPEventArgs> GrowUPEvent;

        protected virtual void OnGrowUp(growUPEventArgs e)
        {
            //handler是一个临时变量，防止被一个竞争占用
            EventHandler<growUPEventArgs> handler = GrowUPEvent;
            //若handler不为空，则发行一个事件,this就是发行者person
            if (handler != null)
            {
                handler(this, e);
            }
        }
        // 定义一个方法来触发事件
       public abstract void growUp();
    }

    class student : person
    {
        public student(string name, int age) : base(name, age) { }

       protected override void OnGrowUp(growUPEventArgs e)
       {
           base.OnGrowUp(e);
       }

       public override void growUp()
       {
           this.OnGrowUp(new growUPEventArgs("Yeah,I'm getting older!"));
           //throw new NotImplementedException();
       }

    }

    class teacher : person
    {
        public teacher(string name, int age) : base(name, age) { }

        protected override void OnGrowUp(growUPEventArgs e)
        {
            base.OnGrowUp(e);
        }

        public override void growUp()
        {
            this.OnGrowUp(new growUPEventArgs("Oh,NO!I'm getting older!"));
            //throw new NotImplementedException();
        }
    }

    class InAclassRoom
    {
        private  List
<person> _PersonList;

        public InAclassRoom()
        {
            _PersonList=new List
<person>();
        }

        public void addPeople(person p)
        {
            _PersonList.Add(p);
            p.GrowUPEvent += HandlerYourGrowUp;

        }

        private void HandlerYourGrowUp(object o,growUPEventArgs e)
        {
            Console.WriteLine(e.Message);
        }

        public List
<person> getThePersonList()
        {
            return _PersonList;
        }
    }

    class Program
    {
        public static void Main()
        {
            teacher t = new teacher("MicroTeach", 40);
            student s = new student("Shaomingbo", 23);
            InAclassRoom classRoom = new InAclassRoom();
            classRoom.addPeople(t);
            classRoom.addPeople(s);
            //订阅了事件，但未触发。按回车后，方可触发;
            //此处说明了，事件发行者决定事件<何时发生>
            Console.WriteLine("You decide:<Enter>");
            Console.ReadLine();
            List
<person> plist = classRoom.getThePersonList();
            foreach (person p in plist)
            {
                Console.WriteLine("Hi, My Name is " + p.Name + ",and i'm " + p.Age + " years old.");
                Console.WriteLine("Actually ,i'm a " + p.GetType());
                Console.WriteLine("When I feel getting older,i'd say :");
                p.growUp();
                Console.WriteLine();
            }
            Console.ReadLine();
        }
    }
}
/*Output:
You decide:<Enter>

Hi, My Name is MicroTeach,and i'm 40 years old.
Actually ,i'm a learningLab.teacher
When I feel getting older,i'd say :
Oh,NO!I'm getting older!

Hi, My Name is Shaomingbo,and i'm 23 years old.
Actually ,i'm a learningLab.student
When I feel getting older,i'd say :
Yeah,I'm getting older!
*/
</pre>
<p>接口层次的设计，其实也应该来写写。但，由于还欠了好多笔记没整理暂时先停在这里。其中值得一提的是，一个类似于属性的事件访问器。其他的和继承实现没太多区别。</p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/12/02/customize-event-in-csharp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>cSharp数组的学习笔记</title>
		<link>http://shao.mingbo.de/2009/11/29/arrays-notes-in-csharp/</link>
		<comments>http://shao.mingbo.de/2009/11/29/arrays-notes-in-csharp/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 05:01:21 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[接口]]></category>
		<category><![CDATA[数组]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=302</guid>
		<description><![CDATA[这一章主要是2对接口的辨析让人纠结。不过，我们还是一对一对的来看，首先将要出场的是IEnumerable Vs IEnumerator. 
IEnumerable 接口中需要实现一个GetEnumerator()方法，它返回一个IEnumerator 接口。在IEnumerator 中有MoveNext()  方法和Reset() 方法，另外还有一个current 属性。这是他们之间的关系。
值得注意的是，不论是否声明继承了接口，在指定类中实现了一个返回IEnumerator 的方法，就可以手动的通过上述的这2个方法和1个属性，进行迭代了；同样的，不论是否有显式的声明，实现了一个返回IEnumerable 的方法，就可以通过foreach 进行迭代了。下面是我推荐的一个Demo:

        static void Main(string[] args)
        {
            testClass myTest = new testClass();
         [...]]]></description>
			<content:encoded><![CDATA[<p>这一章主要是2对接口的辨析让人纠结。不过，我们还是一对一对的来看，首先将要出场的是<strong>IEnumerable Vs IEnumerator. </strong></p>
<p>IEnumerable 接口中需要实现一个GetEnumerator()方法，它返回一个IEnumerator 接口。在IEnumerator 中有<strong>MoveNext()  方法</strong>和<strong>Reset() 方法</strong>，另外还有一个current 属性。这是他们之间的关系。</p>
<p><strong>值得注意的是</strong>，不论是否声明继承了接口，在指定类中实现了一个返回IEnumerator 的方法，就可以手动的通过上述的这2个方法和1个属性，进行迭代了；同样的，不论是否有显式的声明，实现了一个返回IEnumerable 的方法，就可以通过foreach 进行迭代了。下面是我推荐的一个Demo:</p>
<pre lang="csharp">
        static void Main(string[] args)
        {
            testClass myTest = new testClass();
            Console.WriteLine("由于在testClass 已经实现了 GetEnumerator()方法：");
            //直接使用foreach来进行迭代。
            foreach (string a in myTest)
            {
                Console.WriteLine(a);
            }

            //手动迭代
            Console.WriteLine();
            Console.WriteLine("手动迭代：");
            IEnumerator enmuerator = myTest.GetEnumerator();
            while (enmuerator.MoveNext())
            {
                Console.WriteLine(enmuerator.Current.ToString());
            }

            //之所以用手动迭代，是因为不能这样
            //foreach (string a in enmuerator)
            //{
            //    Console.WriteLine(a);
            //}
            //原因是，enmuerator不包含“GetEnumerator”的公共定义
            //foreach无法发现这个定义，但IEnumerable则不同

            Console.WriteLine();
            Console.WriteLine("IEnumerable 还是强悍一些：");
            foreach (string a in myTest.Reverse())
            {
                Console.WriteLine(a);
            }
        }

        class testClass
        {
            string[] cars ={ "BMW Li 5", "Mercedes-benz", "Hong Qi" };

             public IEnumerator GetEnumerator()
            {
                for (int i = 0; i < cars.Length; i++)
                    yield return cars[i];
            }

            public IEnumerable Reverse()
            {
                for (int i = cars.Length-1; i >= 0; i--)
                {
                    yield return cars[i];
                }
            }
        }
</pre>
<p>在介绍下面的接口之前，我还想补充一个有趣的继承关系：IEnumerable 是基类，接下里有ICollection 继承它，而Ilist 继承ICollection。伴随着这样的继承关系，自然地其实现的方法和属性那是越来越多的。接下来，我们该说说<strong>IComparable Vs IComparer </strong>了<strong>.</strong></p>
<p>IComparable 是为指定类型提供了CompareTo() 的方法[<span style="color: #ff0000;"><strong>必须</strong></span>]来比较自己 .当你将指定的类声明为一个数组时，想用sort() 方法来对数组中的对象进行排序，这时如果已经实现了IComparable 则会自动调用CompareTo() 来进行比较排序。</p>
<p>而IComparer则是为指定类型提供了一种<strong><span style="color: #ff0000;">附加</span>的比较机制</strong>。IComparer 附加的被实现为一个辅助比较的类，在该辅助类中提供一个Compare 方法[<strong><span style="color: #ff0000;">必须</span></strong>]。在指定对象的数组中，调用sort 方法时，只需传递一个该辅助类的实例，即可。由于是附加的，所以可以提供多种含有Compare 方法的辅助类，相比之下，IComparable 只能在指定类中实现一个CompareTo 的方法；从效能方面，2种方法的参数都是传递object。但不同的是，CompareTo只有一个参数。每次进行比较，Compare都需要2倍于前者的“装箱-拆箱”的操作。下面，我还是用一个Demo 来说明问题：</p>
<pre lang="csharp">
        static void Main(string[] args)
        {
            mobilePhone[] mp = { new mobilePhone("Sony Ericsson",2000M),
                                 new mobilePhone("Nokia",3000M),
                                 new mobilePhone("Samsung",1500M),
                                 new mobilePhone("Shan Zhai",800M),
                                 new mobilePhone("ABC",800M),
                                 new mobilePhone("ACC",700M)
                                };
            //------------
            Console.WriteLine("IComparable Demo:");
            Array.Sort(mp);
            foreach (mobilePhone m in mp)
            {
                Console.WriteLine(m);
            }
            Console.WriteLine();
            //------------
            Console.WriteLine("IComparer-makerASCEcomparer Demo:");
            Array.Sort(mp, mobilePhone.makerASCEcomparer());
            foreach (mobilePhone m in mp)
            {
                Console.WriteLine(m);
            }
            Console.WriteLine();
            //------------
            Console.WriteLine("IComparer-priceASCEcomparer Demo:");
            Array.Sort(mp, mobilePhone.priceASCEcomparer());
            foreach (mobilePhone m in mp)
            {
                Console.WriteLine(m);
            }
            Console.WriteLine();
            //------------
            Console.WriteLine("IComparer-priceDSCEcomparer Demo:");
            Array.Sort(mp, mobilePhone.priceDSCEcomparer());
            foreach (mobilePhone m in mp)
            {
                Console.WriteLine(m);
            }
            Console.WriteLine();
        }

        class mobilePhone:IComparable
        {
            private string maker;
            private decimal price;

            public mobilePhone(string maker,decimal price)
            {
                this.maker = maker;
                this.price = price;
            }

            public string Maker
            {
                get
                {
                    return maker;
                }
                set
                {
                    maker = value;
                }
            }

            public decimal Price
            {
                get
                {
                    return price;
                }
                set
                {
                    price = value;
                }
            }

            int IComparable.CompareTo(object x)
            {
                mobilePhone other = (mobilePhone)x;
                int result = this.price.CompareTo(other.price);
                if (result == 0)
                    this.maker.CompareTo(other.maker);
                return result;
            }

            private class priceASCE : IComparer
            {
                int IComparer.Compare(object x,object y)
                {
                    mobilePhone one = (mobilePhone)x;
                    mobilePhone other = (mobilePhone)y;

                    if (one.Price > other.Price)
                        return 1;
                    else if (one.Price == other.Price)
                        return 0;
                    else
                        return -1;

                }
            }

            public static IComparer priceASCEcomparer()
            {
                return (IComparer)new priceASCE();
            }

            private class priceDSCE : IComparer
            {
                int IComparer.Compare(object x, object y)
                {
                    mobilePhone one = (mobilePhone)x;
                    mobilePhone other = (mobilePhone)y;

                    if (one.Price < other.Price)
                        return 1;
                    else if (one.Price == other.Price)
                        return 0;
                    else
                        return -1;

                }
            }

            public static IComparer priceDSCEcomparer()
            {
                return (IComparer)new priceDSCE();
            }

            private class makerASCE : IComparer
            {
                int IComparer.Compare(object x, object y)
                {
                    mobilePhone one = (mobilePhone)x;
                    mobilePhone other = (mobilePhone)y;

                    int result = one.Maker.CompareTo(other.Maker);
                    return result;
                }
            }

            public static IComparer makerASCEcomparer()
            {
                return (IComparer)new makerASCE();
            }

            public override string ToString()
            {
                return "Mobile Made by " + Maker + ", And Its Price is " + Price.ToString("C");
            }
        }
</pre>
<p>其实，不得不说，不管是IComparable 还是IComparer 都能实现彼此的功能，IComparer 更符合人类排序比较的思维方式罢了。当然理性的对待问题：首先是要看对效能的需求，其次才是看个人的喜好了。</p>
<p>参考资料：<br />
MSDN——<a href="http://support.microsoft.com/kb/320727/en-us/">How to use the IComparable and IComparer interfaces in Visual C#</a></p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/11/29/arrays-notes-in-csharp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cSharp继承的学习笔记-PartTwo</title>
		<link>http://shao.mingbo.de/2009/11/28/inheritance-notes-of-csharp-part-two/</link>
		<comments>http://shao.mingbo.de/2009/11/28/inheritance-notes-of-csharp-part-two/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 07:06:56 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[密封]]></category>
		<category><![CDATA[接口]]></category>
		<category><![CDATA[继承]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=297</guid>
		<description><![CDATA[本文承接于《cSharp继承的学习笔记-PartOne》，主要谈谈继承这一章节关于密封和接口中我认为重要的知识。
密封：对于类来说，不能继承该类；对方法来说，不能重写。

在《对象和类》中提到，结构本身是不支持类型继承，那是因为结构是隐式密封的。
在方法中或属性中使用sealed 关键字时，必须与override连用。

接口：只能包含方法，属性，索引和事件；不能包含构造函数（其本身，不允许实例化，何谈构造？），不允许运算符重载（引起.net 的其他语言不兼容的问题，如：VB）
接口可以理解为一种契约，当你和别人签订了契约，就有责任实现其中的每个方法，如若有一个方法没实现，那请不要签定该契约。当契约生效时，其他的c#代码便可通过接口知道该方法支持的特性。
]]></description>
			<content:encoded><![CDATA[<p>本文承接于《<a href="http://shao.mingbo.de/2009/11/28/inheritance-notes-of-csharp-part-one/" target="_blank">cSharp继承的学习笔记-PartOne</a>》，主要谈谈继承这一章节关于<strong>密封和接口</strong>中我认为重要的知识。</p>
<p><strong>密封</strong>：对于类来说，不能继承该类；对方法来说，不能重写。</p>
<ul>
<li>在《<a href="http://shao.mingbo.de/2009/11/26/object-and-class-in-csharp/" target="_blank">对象和类</a>》中提到，结构本身是不支持类型继承，那是因为结构是隐式密封的。</li>
<li>在方法中或属性中使用sealed 关键字时，必须与override连用。</li>
</ul>
<p><strong>接口</strong>：只能包含方法，属性，索引和事件；不能包含构造函数（其本身，不允许实例化，何谈构造？），不允许运算符重载（引起.net 的其他语言不兼容的问题，如：VB）</p>
<p><strong>接口</strong>可以理解为一种契约，当你和别人签订了契约，<span style="color: #ff0000;">就有责任实现其中的每个方法</span>，如若有一个方法没实现，那请不要签定该契约。当契约生效时，其他的c#代码便可通过接口知道该方法支持的特性。</p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/11/28/inheritance-notes-of-csharp-part-two/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>cSharp继承的学习笔记-PartOne</title>
		<link>http://shao.mingbo.de/2009/11/28/inheritance-notes-of-csharp-part-one/</link>
		<comments>http://shao.mingbo.de/2009/11/28/inheritance-notes-of-csharp-part-one/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 16:35:28 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[继承]]></category>
		<category><![CDATA[隐藏函数]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=289</guid>
		<description><![CDATA[在昨天的笔记中提到“结构本身不支持继承”，实际上有些武断。结构不能建立类型层次，但结构可以实现接口。
c# 的隐藏方法，这一块一直都觉得挺晦涩难懂。实际上，是没有理解出，它和虚函数之间的关系。下面以一个例子说明：
        static void Main(string[] args)
        {

            testClass t = new testClass2();
            t.myMethod();
       [...]]]></description>
			<content:encoded><![CDATA[<p>在昨天的笔记中提到“结构本身不支持继承”，实际上有些武断。结构不能建立类型层次，但结构可以实现接口。</p>
<p><strong>c# 的隐藏方法</strong>，这一块一直都觉得挺晦涩难懂。实际上，是没有理解出，它和虚函数之间的关系。下面以一个例子说明：</p>
<pre name="code" class="c-sharp">        static void Main(string[] args)
        {

            testClass t = new testClass2();
            t.myMethod();
            t.my();
        }

        class testClass
        {
            public void myMethod()
            {
                Console.WriteLine("In base method");
            }

            public virtual void my()
            {
                Console.WriteLine("Virtual in base");
            }

        }

        class testClass2 : testClass
        {
            public new void myMethod()
            {
                Console.WriteLine("In child method");
            }

            public override void my()
            {
                Console.WriteLine("override in derived");
            }
        }</pre>
<ul>
<li>有没有new 这个显式的声明隐藏方法的形式，不是必须的。如果没有，则编译器会还会警告你，它会默认的按照隐藏基类的方法执行。</li>
<li>从编译结果看来，隐藏函数和虚函数的区别是，override 虚函数后，用基类引用子类的实例并调用该函数，会显示其多态性。但，隐藏函数则会直接显示其基类中的相关函数。</li>
</ul>
<p>&#8212;&#8212;&#8212;&#8212;以下与笔记无关&#8212;&#8212;&#8212;&#8212;</p>
<p>最近这两天的效率实在是低。昨天是相当于一整天只更新了一篇关于《<a href="http://shao.mingbo.de/2009/11/26/object-and-class-in-csharp/" target="_blank">对象和类</a>》的日志，而今天只看了<strong>继承</strong>这一章的1/6 的内容。持续的低迷，精神状态是一方面的原因——午睡的时间给耽误了，加上早先的几天的熬夜，显得这几天看书效率低了好几个档次。另外，今天下午还是铁着心，跑出去买了一个<a href="http://www.pny.com.cn/news_1.asp?ID=110" target="_blank">PNY 的浪漫紫罗双子盘</a>+<a href="http://www.onda.cn/pro/product/product.jsp?Id=14412&amp;PT=2" target="_blank">一个昂达的方块糖P3 </a>，很心疼的说。提起U盘，那真是一头包的，月头才买不久的Sandisk 就神不知鬼不觉的不见了；提起这次买的P3，让我想起04 年那会，昂达刚出第一款<a href="http://www.onda.cn/pro/product/product.jsp?Id=4305&amp;PT=2" target="_blank">vx505</a> 时，我就买了。</p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/11/28/inheritance-notes-of-csharp-part-one/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
