<?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:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<channel>
	<title>雪狼领地 - DotNet框架</title>
	<link>http://blog.0734link.com/Folder/dotnet/Index.aspx</link>
	<language>zh-CN</language>
	<webMaster>329084470@qq.com(ceiling)</webMaster>
	<pubDate>Wed, 24 Jun 2009 02:31:06 GMT</pubDate>
	<copyright>Copyright 2007-2009. All rights reserved.</copyright>
	<generator>Bitrac Free Version</generator>
	<description>雪狼领地—技术成就梦想！ 男儿不展风云志，空负天生八尺躯</description>
	<image>
		<title>雪狼领地</title>
		<url>http://blog.0734link.com/Client/Banner.gif</url>
		<link>http://blog.0734link.com/</link>
		<description>雪狼领地—技术成就梦想！ 男儿不展风云志，空负天生八尺躯</description>
	</image>
	<item>
		<link>http://blog.0734link.com/Article/668.aspx</link>
		<title>C#IO文件读写和流</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Wed, 02 Mar 2011 16:18:04 GMT</pubDate>
		<description>&lt;p&gt;一 流的概念&lt;br /&gt;在.NET中Stream 是所有流的抽象基类。流是字节序列的抽象概念，或者说是计算机在处理文件或数据时产生的二进制序列。例如文件、输入/输出设备、内部进程通信管道或者 TCP/IP 套接字。Stream 类及其派生类提供这些不同类型的输入和输出的一般视图，使程序员不必了解操作&lt;span class=&quot;t_tag&quot; onclick=&quot;tagshow(event)&quot; href=&quot;tag.php?name=%CF%B5%CD%B3&quot;&gt;系统&lt;/span&gt;和基础设备的具体细节。简单的说流提供了不同介质之间的数据交互&lt;span class=&quot;t_tag&quot; onclick=&quot;tagshow(event)&quot; href=&quot;tag.php?name=%B9%A6%C4%DC&quot;&gt;功能&lt;/span&gt;。&lt;br /&gt;&lt;br /&gt;在.NET中常用的流有BufferedStream 、FileStream、MemoryStream&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;和NetworkStream，他们都是位于System.IO和System.Net命名&lt;span class=&quot;t_tag&quot; onclick=&quot;tagshow(event)&quot; href=&quot;tag.php?name=%BF%D5%BC%E4&quot;&gt;空间&lt;/span&gt;下。流涉及三个基本操作： 读取，写入和查找。根据基础数据源或储存库，流可能只支持这些功能中的一部分。有些流实现执行基础数据的本地缓冲以提高性能。对于这样的流，Flush 方法可用于清除所有内部缓冲区并确保将所有数据写入基础数据源或储存库。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;二 文件读写&lt;br /&gt;对于文件的读写，实际是把&lt;span class=&quot;t_tag&quot; onclick=&quot;tagshow(event)&quot; href=&quot;tag.php?name=%D3%B2%C5%CC&quot;&gt;硬盘&lt;/span&gt;中的数据读入&lt;span class=&quot;t_tag&quot; onclick=&quot;tagshow(event)&quot; href=&quot;tag.php?name=%C4%DA%B4%E6&quot;&gt;内存&lt;/span&gt;和把内存的数据写入硬盘，他们数据之间的交换就是通过流来完成的。在.NET中这个功能是由FileStream类完成的。他提供的Write和Read方法可以对文件进行读写操作。&lt;br /&gt;&lt;br /&gt;1：FileStream读写文件&lt;br /&gt;使用 FileStream 类对文件系统上的文件进行读取、写入、打开和关闭操作，并对其他与文件相关的操作系统句柄进行操作，如管道、标准输入和标准输出。读写操作可以指定为同步或异步操作。FileStream 对输入输出进行缓冲，从而提高性能。&lt;br /&gt;&lt;br /&gt;view plaincopy to clipboardprint?&lt;br /&gt;static void Main(string[] args)&amp;nbsp; &amp;nbsp;&lt;br /&gt;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; try&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;FileStream fs = new FileStream(@&amp;quot;c:\text.txt&amp;quot;, FileMode.Create);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;string message = &amp;quot;This is example for filestream&amp;quot;;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;byte[] writeMesaage = Encoding.UTF8.GetBytes(message);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;fs.Write(writeMesaage, 0, writeMesaage.Length);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch (Exception ex)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(ex.Message);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; finally&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.ReadKey();&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&lt;br /&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; try&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;FileStream fs = new FileStream(@&amp;quot;c:\text.txt&amp;quot;, FileMode.Create);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;string message = &amp;quot;This is example for filestream&amp;quot;;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;byte[] writeMesaage = Encoding.UTF8.GetBytes(message);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;fs.Write(writeMesaage, 0, writeMesaage.Length);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch (Exception ex)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(ex.Message);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; finally&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.ReadKey();&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;上面是一个简单的例子，把一条字符串写入到文件中。首先建立一个FileStream对象，指定文件和读写方式（具体读写方式和权限可以参加MSDN）。接下来把要写入的字符串以一定的编码格式存入一个字节数组中，然后调用Writer方法写入文件。运行程序，当程序执行到Console.ReadKey方法时去查看文件发现文件中内容是空的。也就是说调用Writer方法后内容并没有被写入到文件中。&lt;br /&gt;&lt;br /&gt;这里就要谈到流中的缓冲区的问题了。缓冲区是为了提高I/O效率而设置的，我们知道读写的I/O操作是很费时的，如果每一个字节都马上写入到文件中整个过程就会很慢，所以设置缓冲区，写把要写入的内容写入到缓冲区中，然后在一次性写入到文件中，来提高写入的效率和速度。而Write方法实际上只是把数据写入到流的缓冲区中，而不是真正的写入到文件中。所以调用Writer方法并不能完成文件的写入。于是FileStream对象提供了一个把缓冲区写入文件的方法，那就是Flush方法。&lt;br /&gt;&lt;br /&gt;Flush：清除该流的所有缓冲区会使得所有缓冲的数据都将写入到文件系统。这是MSDN给出的定义，可以看到，只有调用了Flush方法后数据才会被真正的写入到文件中。所以这里就又另外一个问题，那就是可能存在写入失败。比如上面在Writer方法结束后发生了异常，那么数据就无法写入到文件中了。所以我们在调用Writer方法后可以显式的调用Flush方法来把数据写入到文件中。但是上面的方法结束后又会发现数据被写入了。其实这是因为在程序结束时，销毁FileStream对象时，系统自动调用了Flush方法来保证内容被写入到文件中。而在FileStream对象中，很多地方都调用了这个方法，比如Close方法和Dispose方法。所以在程序中，调用这2个方法销毁对象时也会把数据从缓冲区写入文件。所以使用FileStream对象Writer方法后只要不抛出异常，缓冲区数据总会被写入文件（当然也可能因为磁盘已满而在写入是抛出异常）。但是我们最好还是显示的调用Close方法或使用using块关闭对象，使数据写入。或是调用Flush方法。Flush方法内部调用API的internal static extern unsafe int WriteFile方法实现文件写入。&lt;br /&gt;&lt;br /&gt;对于读取文件内容也是类似的，要先把数据读取到字节数组中。而且还提供了BeginRead和BeginWrite方法进行异步读写操作。&lt;br /&gt;&lt;br /&gt;2 StreamWriter写文件&lt;br /&gt;上面的FileStream操作文件读写，每次都需要使用字节数组，因为FileStream操作对象是字节。而.NET提供了StreamWriter和StreamReader对象来对流进行读写操作。&lt;br /&gt;&lt;br /&gt;他的构造函数可以接受一个Stream对象。从而对流进行操作。他们的内部有个一Stream对象来维护传入的各种流对象。并且也提供了Write和Read方法。实际上这2个类是对流读写的的一个包装，方便我们使用。当我们传一个流对象时，调用读写方法是，实际调用该对象自己重写的方法。而当我们在构造函数中传入的是文件路径时，他就成为了对文件读写的操作。因为他在内部构建了一个FileStream对象，并交给内部的Stream对象维护。&lt;br /&gt;&lt;br /&gt;view plaincopy to clipboardprint?&lt;br /&gt;public StreamWriter(string path) : this(path, false, UTF8NoBOM, 0x400)&amp;nbsp; &amp;nbsp;&lt;br /&gt;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;br /&gt;public StreamWriter(string path, bool append, Encoding encoding, int bufferSize) : base(null)&amp;nbsp; &amp;nbsp;&lt;br /&gt;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; if ((path == null) || (encoding == null))&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ArgumentNullException((path == null) ? &amp;quot;path&amp;quot; : &amp;quot;encoding&amp;quot;);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; if (bufferSize &amp;lt;= 0)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ArgumentOutOfRangeException(&amp;quot;bufferSize&amp;quot;, Environment.GetResourceString(&amp;quot;ArgumentOutOfRange_NeedPosNum&amp;quot;));&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Stream stream = CreateFile(path, append);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; this.Init(stream, encoding, bufferSize);&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;private static Stream CreateFile(string path, bool append)&amp;nbsp; &amp;nbsp;&lt;br /&gt;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, 0x1000, FileOptions.SequentialScan);&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&lt;br /&gt;public StreamWriter(string path) : this(path, false, UTF8NoBOM, 0x400)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public StreamWriter(string path, bool append, Encoding encoding, int bufferSize) : base(null)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; if ((path == null) || (encoding == null))&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ArgumentNullException((path == null) ? &amp;quot;path&amp;quot; : &amp;quot;encoding&amp;quot;);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; if (bufferSize &amp;lt;= 0)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ArgumentOutOfRangeException(&amp;quot;bufferSize&amp;quot;, Environment.GetResourceString(&amp;quot;ArgumentOutOfRange_NeedPosNum&amp;quot;));&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; Stream stream = CreateFile(path, append);&lt;br /&gt;&amp;nbsp; &amp;nbsp; this.Init(stream, encoding, bufferSize);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;private static Stream CreateFile(string path, bool append)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, 0x1000, FileOptions.SequentialScan);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;通过上面的&lt;span class=&quot;t_tag&quot; onclick=&quot;tagshow(event)&quot; href=&quot;tag.php?name=%B4%FA%C2%EB&quot;&gt;代码&lt;/span&gt;，可以看到我们使用 public StreamWriter(string path)构造方法和我们自己新建一个FileStream对象传递给StreamWriter(Stream)构造方法是一样的。不同的是后者还可对其他继承与Stream的流进行操作。而且可以指定文件读取的方式和访问权限以及缓冲区大小。&lt;br /&gt;&lt;br /&gt;view plaincopy to clipboardprint?&lt;br /&gt;static void Main(string[] args)&amp;nbsp; &amp;nbsp;&lt;br /&gt;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; try&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;StreamWriter sw = new StreamWriter(@&amp;quot;c:\text.txt&amp;quot;);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Write(&amp;quot;This is StreamWriter&amp;quot;);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch (Exception ex)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(ex.Message);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; finally&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.ReadKey();&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&lt;br /&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; try&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;StreamWriter sw = new StreamWriter(@&amp;quot;c:\text.txt&amp;quot;);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Write(&amp;quot;This is StreamWriter&amp;quot;);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch (Exception ex)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(ex.Message);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; finally&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.ReadKey();&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;上面的代码是使用StreamWriter对文件进行写操作，当执行到ReadKey时，我们发现文件没有被写入，这个和FileStream是一样的，但是当程序执行完后我们发现，数据还是没有被写入。如果我们写入的数据量比较大时，数据也被写入到文件中，但是会发现写入的数据可能并不完整。因为只有当StreamWriter内部的缓冲区充满或调用Flush时，才会把数据写入Stream对象中。StreamWriter 未将最后 1 至 4 KB 数据写到文件。后面会具体解释。&lt;br /&gt;&lt;br /&gt;MSDN中对此的解释是：&lt;br /&gt;&lt;br /&gt;StreamWriter 在内部缓冲数据，这需要调用 Close 或 Flush 方法将缓冲数据写到基础数据存储区。如果没有适当地调用 Close 或 Flush，StreamWriter 实例中缓冲的数据可能不会按预期写出。&lt;br /&gt;&lt;br /&gt;在StreamWriter中也有Flush方法，清理当前编写器的所有缓冲区，并使所有缓冲数据写入基础流。对于StreamWriter来说，也有自己的缓冲区，而不同的是StreamWriter缓冲区是char[]而不是byte[]。而StreamWriter的write方法只是把数据写入到自己的缓冲区中，所以我们必须条用Flush方法来写入到文件中，而Flush方法中则是先调用了FileStream的write方法把StreamWriter缓冲区的数据写入到FileStream的缓冲区中，最后在调用FileStream的Flush方法写入文件。&lt;br /&gt;&lt;br /&gt;view plaincopy to clipboardprint?&lt;br /&gt;//StreamWriter.write把数据写入StreamWriter缓冲区中&amp;nbsp; &amp;nbsp;&lt;br /&gt;public override void Write(string value)&amp;nbsp; &amp;nbsp;&lt;br /&gt;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; if (value != null)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;int length = value.Length;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;int sourceIndex = 0;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;while (length &amp;gt; 0)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;if (this.charPos == this.charLen)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; this.Flush(false, false);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;int count = this.charLen - this.charPos;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;if (count &amp;gt; length)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; count = length;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;value.CopyTo(sourceIndex, this.charBuffer, this.charPos, count);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.charPos += count;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;sourceIndex += count;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;length -= count;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;if (this.autoFlush)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.Flush(true, false);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;//StreamWriter.Flush把StreamWriter缓冲区内容写入Stream的缓冲区&amp;nbsp; &amp;nbsp;&lt;br /&gt;private void Flush(bool flushStream, bool flushEncoder)&amp;nbsp; &amp;nbsp;&lt;br /&gt;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; if (this.stream == null)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;__Error.WriterClosed();&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; if (((this.charPos != 0) || flushStream) || flushEncoder)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;if (!this.haveWrittenPreamble)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.haveWrittenPreamble = true;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;byte[] preamble = this.encoding.GetPreamble();&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;if (preamble.Length &amp;gt; 0)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; this.stream.Write(preamble, 0, preamble.Length);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;int count = this.encoder.GetBytes(this.charBuffer, 0, this.charPos, this.byteBuffer, 0, flushEncoder);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;this.charPos = 0;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;if (count &amp;gt; 0)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.stream.Write(this.byteBuffer, 0, count);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;if (flushStream)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.stream.Flush();&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&lt;br /&gt;//StreamWriter.write把数据写入StreamWriter缓冲区中&lt;br /&gt;public override void Write(string value)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; if (value != null)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;int length = value.Length;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;int sourceIndex = 0;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;while (length &amp;gt; 0)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;if (this.charPos == this.charLen)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; this.Flush(false, false);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;int count = this.charLen - this.charPos;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;if (count &amp;gt; length)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; count = length;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;value.CopyTo(sourceIndex, this.charBuffer, this.charPos, count);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.charPos += count;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;sourceIndex += count;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;length -= count;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;if (this.autoFlush)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.Flush(true, false);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//StreamWriter.Flush把StreamWriter缓冲区内容写入Stream的缓冲区&lt;br /&gt;private void Flush(bool flushStream, bool flushEncoder)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; if (this.stream == null)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;__Error.WriterClosed();&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; if (((this.charPos != 0) || flushStream) || flushEncoder)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;if (!this.haveWrittenPreamble)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.haveWrittenPreamble = true;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;byte[] preamble = this.encoding.GetPreamble();&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;if (preamble.Length &amp;gt; 0)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; this.stream.Write(preamble, 0, preamble.Length);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;int count = this.encoder.GetBytes(this.charBuffer, 0, this.charPos, this.byteBuffer, 0, flushEncoder);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;this.charPos = 0;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;if (count &amp;gt; 0)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.stream.Write(this.byteBuffer, 0, count);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;if (flushStream)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.stream.Flush();&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;通过上面的代码可以明白，真正完成写入文件的也是Flush方法，因为它的工作是调用了FileStream的write和flush方法。而在StreamWriter的Close和Dispose的方法中则是调用了StreamWriter的Flush方法写入文件，然后用FileStream.Close方法关闭流。&lt;br /&gt;&lt;br /&gt;所以在关闭具有 StreamWriter 的实例的应用程序或任何代码块之前，确保调用 StreamWriter 的 Close 或 Flush。达到此目的的最佳机制之一是用 C# using 块创建该实例，这样将确保调用编写器的 Dispose 方法，从而正确关闭该实例。另外在StreamWriter中有一个AutoFlush属性，如果设置为True，则在调用writer方法后会自动调用Flush方法。&lt;br /&gt;&lt;br /&gt;3 FileStream和StreamWriter的依赖关系&lt;br /&gt;如果我们使用public StreamWriter(string path)构造方法不会存在这个问题，因为FileStrem对象是内部控制的，如果我们用StreamWriter(Stream)构造方法就可能存在一些问题。&lt;br /&gt;&lt;br /&gt;view plaincopy to clipboardprint?&lt;br /&gt;static void Main(string[] args)&amp;nbsp; &amp;nbsp;&lt;br /&gt;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; FileStream fs = null；&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;StreamWriter sw = null；&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; try&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;fs = new FileStream(@&amp;quot;c:\text.txt&amp;quot;, FileMode.Create);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;sw = new StreamWriter(fs);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;string message = &amp;quot;This is StreamWriter\r\n&amp;quot;;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;for (int i = 0; i &amp;lt; 10; i++)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;message += message;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Write(message);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch (Exception ex)&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(ex.Message);&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; finally&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;fs.Close();&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Close();&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.ReadKey();&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&lt;br /&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; FileStream fs = null；&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;StreamWriter sw = null；&lt;br /&gt;&amp;nbsp; &amp;nbsp; try&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;fs = new FileStream(@&amp;quot;c:\text.txt&amp;quot;, FileMode.Create);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;sw = new StreamWriter(fs);&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;string message = &amp;quot;This is StreamWriter\r\n&amp;quot;;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;for (int i = 0; i &amp;lt; 10; i++)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;message += message;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Write(message);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch (Exception ex)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(ex.Message);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; finally&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;fs.Close();&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Close();&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;Console.ReadKey();&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;执行上面的代码的时候会出现Dispose异常，无法访问已经关闭的文件。这是因为我们先关闭了文件流，然后在关闭StreamWriter对象。而StreamWriter对象的Close方法实际是关闭当前的 StreamWriter 对象和基础流。也就是说我们只需调用这一个方法就可以了。而如果在数据写入前调用了FileStream的Close方法，那么数据最终是无法写入的，还会引发异常。所以在写入文件时，最好只调用StreamWriter对象的Close方法就行了。&lt;br /&gt;&lt;br /&gt;上面说过了没有调用Close方法导致部分数据没有写入，这是因垃圾回收造成的。当我们调用完write方法后，没有调用close，系统发现StreamWriter和FileStream对象不可达，会对他们进行终结操作，但是终结的顺序是不确定的。如果先关闭了FileStream会出现数据无法写入。&lt;span class=&quot;t_tag&quot; onclick=&quot;tagshow(event)&quot; href=&quot;tag.php?name=%CE%A2%C8%ED&quot;&gt;微软&lt;/span&gt;为了避免这种情况，就不让StreamWriter方法实现Finalize方法，这样，在程序结束时，没有执行StreamWriter的Finalize方法，也就无法把缓冲区的数据写入FileStream中。而FileStream内部实现了Finalize方法。这也就是为什么FileStream不关闭仍然可以把数据写入文件。所以在使用StreamWriter对象时不显调用Close方法时，缓冲区的数据一定会丢失。&lt;br /&gt;&lt;br /&gt;而且WriterStream的内部缓冲区填满后会自动写入到Stream流中。所以当我们写入的数据很少时，不够填充满数据缓冲区，而且不关闭对象，必然无法写入文件。而当我们写大量数据时，一部分数据在缓冲区满的时候被写入了Stream中，当我们不关闭对象，直接结束程序时，Stream会执行Finalize方法，把数据写入文件，而StreamWriter没有此方法，而且默认的缓冲区大小为4K。如果此时缓冲区中还有数据必定无法被写入，而且大小是1-4K。&lt;br /&gt;&lt;br /&gt;3 BinaryWriter&lt;br /&gt;BinaryWriter对象也可以用写文件，以二进制形式将基元类型写入流，并支持用特定的编码写入字符串。与StreamWriter不同的是，他不存在缓冲区丢失的问题。因为他每次调用Write方法以后说首先把数据写入自己的char[]数组，然后转换为指定编码的Byte[]数组，最后调用Stream的Write方法写入到流的缓冲区。&lt;br /&gt;&lt;br /&gt;BinaryWriter对象也有Flush方法，但是只是简单的调用了Stream的Flush方法，而他的Close和Dispose方法则是调用了Stream的Close方法。和上面一样 BinaryWriter对象也没有实现Finalize方法，但是因为他没有把数据放到自己的缓冲区，每次都是立即写入到流中。所以即便不调用Flush方法或是显式关闭对象，最后也会全部被写入到文件中，因为数据全部在FileStream的缓冲区中，而程序结束时Finalize方法会调用Flush把数据写入文件。&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/668.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/668/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/668.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/668/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/667.aspx</link>
		<title>c#当前应用程序路径</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Wed, 02 Mar 2011 04:20:34 GMT</pubDate>
		<description>&lt;p&gt;应该算是出于对各种DOCK的烦躁（部分DOCK程序在启动程序时，会把当前路径指派为DOCK所在路径，当程序中使用相对路径时，路径对“相对”到DOCK的文件夹里），我在程序中大多使用绝对路径来定位文件方便后来者，在这里总结了下，也摘抄了点网上流传的以我的程序为例物理路径：&lt;/p&gt;&lt;p&gt;E:\c#学习\获取当前路径\获取当前路径\bin\Debug\获取当前路径.exeSystem.Environment.CurrentDirectory;&lt;br /&gt;//很熟悉了,获取和设置当前目录（即该进程从中启动的目录）的完全限定路径。&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//返回E:\c#学习\获取当前路径\获取当前路径\bin\Debug&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;System.AppDomain.CurrentDomain.BaseDirectory;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//我用的最多的方法，获取当前 Thread 的当前应用程序域的基目录，它由程序集冲突解决程序用来探测程序集。&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//返回 E:\c#学习\获取当前路径\获取当前路径\bin\Debug\&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//获取新的 Process 组件并将其与当前活动的进程关联的主模块的完整路径，包含文件名(进程名)。&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//返回 E:\c#学习\获取当前路径\获取当前路径\bin\Debug\获取当前路径.exe&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//获取和设置包含该应用程序的目录的名称。&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//返回&amp;nbsp; E:\c#学习\获取当前路径\获取当前路径\bin\Debug\&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;System.Windows.Forms.Application.StartupPath;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//获取启动了应用程序的可执行文件的路径，不包括可执行文件的名称。&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//返回 E:\c#学习\获取当前路径\获取当前路径\bin\Debug&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;System.Windows.Forms.Application.ExecutablePath;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//获取启动了应用程序的可执行文件的路径，包括可执行文件的名称。&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//返回&amp;nbsp; E:\c#学习\获取当前路径\获取当前路径\bin\Debug\获取当前路径.exe&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;System.IO.Directory.GetCurrentDirectory();&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//获取应用程序的当前工作目录(不可靠)。&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//返回 E:\c#学习\获取当前路径\获取当前路径\bin\Debug&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//这个方法其实是我最早知道的，但是也是我用的最少的，总感觉基于IO的东西都不怎么可靠&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//至于上面的“（不可靠）”不是我加的，是网上的大大们写的，我只是Copy过来了&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//另外还有一个方法&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;this.GetType().Assembly.Location;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//获取当前进程的完整路径，包含文件名(进程名)。&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//遗憾的静态方法无法使用&lt;br /&gt;&amp;nbsp;&lt;br /&gt;//返回 E:\c#学习\获取当前路径\获取当前路径\bin\Debug\获取当前路径.exe&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/667.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/667/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/667.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/667/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/665.aspx</link>
		<title>.NET/C#中对对象集合进行查询的方法 以及相关的 Predicate&lt;T&gt; 及 Action&lt;T&gt; 的用法</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Sat, 26 Feb 2011 06:05:09 GMT</pubDate>
		<description>&lt;div id=&quot;cnblogs_post_body&quot;&gt;&lt;p&gt;所谓的对对象集合进行查询的方法，就是指，如何从一个集合中找出符合条件的某些项来。这一次我没有用 自定义对象集合，而是直接使用对象集合，是因为普通的对象集合，如int[], List&amp;lt;int&amp;gt;,这样的东西，也没有统一固定的查询方法，因为对于一个查询来讲，它的条件是多种多样的，所以是无法提供统一固定查询方法的。比如有时候想找出所有大于10的int,有时候又想找所有小于10的int。。。。。。。。。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;所以要完成这样一个任务，传统的编程方式就是定义方法，其中建立循环，然后逐个遍历每一个元素，查看其是否符合条件，然后把符合条件的结果挑出来，放在一个返回值集合中，最后返回给调用者。这样的方法直接了当，清晰易懂。用了好多年了，但是写起来麻烦，简单点的都得个7，8行。于是.NET又进行了改进。&lt;/p&gt;&lt;p&gt;这是.NET2.0时代一种比较笨的方法：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;cnblogs_code&quot; onclick=&quot;cnblogs_code_show(&apos;322d8a28-71ad-42b0-9672-560227068f7b&apos;)&quot;&gt;&lt;img style=&quot;display: none&quot; id=&quot;code_img_closed_322d8a28-71ad-42b0-9672-560227068f7b&quot; class=&quot;code_img_closed&quot; src=&quot;http://blog.0734link.com/Attach/month_1102/6cwu3l_140608_1.gif&quot; jquery1298696128055=&quot;2&quot; alt=&quot;&quot; /&gt;&lt;img id=&quot;code_img_opened_322d8a28-71ad-42b0-9672-560227068f7b&quot; class=&quot;code_img_opened&quot; onclick=&quot;cnblogs_code_hide(&apos;322d8a28-71ad-42b0-9672-560227068f7b&apos;,event)&quot; src=&quot;http://blog.0734link.com/Attach/month_1102/65zjga_140609_2.gif&quot; alt=&quot;&quot; /&gt;&lt;span class=&quot;cnblogs_code_collapse&quot;&gt;代码1&lt;/span&gt;&lt;div style=&quot;display: block&quot; id=&quot;cnblogs_code_open_322d8a28-71ad-42b0-9672-560227068f7b&quot; class=&quot;cnblogs_code_hide&quot; jquery1298696128055=&quot;1&quot;&gt;&lt;pre&gt;&lt;div&gt;&lt;span style=&quot;color: #008080&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; System;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; System.Collections.Generic;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; System.Linq;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; System.Text;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; SelectTest1&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt; 7&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt; 8&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Product&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt; 9&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;    {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Name { &lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;; }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;11&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Price { &lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;; }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;13&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Product(&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; name, &lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; price)&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            Name &lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; name;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            Price &lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; price;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;17&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;18&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;19&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Product() { }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; GetSampleProduct()&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;23&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;25&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Product{Name&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;Watch&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;,Price&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #800080&quot;&gt;12345.56m&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;},&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;26&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Product{Name&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;Knife&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;,Price&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #800080&quot;&gt;224.50m&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;},&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Product{Name&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;Rope&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;,Price&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #800080&quot;&gt;12.50m&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;},&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;28&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Product{Name&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;ETorch&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;,Price&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #800080&quot;&gt;5.5m&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;29&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            };&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;31&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;override&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; ToString()&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;33&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;34&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;.Format(&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;{0} : {1}&lt;/span&gt;&lt;span style=&quot;color: #800000&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;, Name, Price);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;35&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;36&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;37&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;38&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Program&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;39&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;    {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;40&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Main(&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;[] args)&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;41&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            List&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; ProductSample &lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Product.GetSampleProduct();&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;43&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;foreach&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; (Product tmp &lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; ProductSample)&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;44&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;45&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;                Console.WriteLine(tmp);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;46&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;47&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;48&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            Console.WriteLine();&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;49&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            Predicate&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; test &lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;delegate&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;(Product p) { &lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; p.Price &lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; 10m; };&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;51&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            List&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; matches &lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; ProductSample.FindAll(test);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;52&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;53&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            Action&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; print &lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;delegate&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;(Product p) { Console.WriteLine(p); };&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;54&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;55&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;            matches.ForEach(print);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;56&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;57&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;58&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008080&quot;&gt;59&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;关键代码是：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Predicate&amp;lt;Product&amp;gt; test = delegate(Product p) { return p.Price &amp;gt; 10m; };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;Product&amp;gt; matches = ProductSample.FindAll(test);&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Action&amp;lt;Product&amp;gt; print = delegate(Product p) { Console.WriteLine(p); };&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; matches.ForEach(print);&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;什么是Predicate,Action 呢？？？？？这两个东西我很陌生。查MSDN!&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Predicate&amp;lt;T&amp;gt; 是一个委托，它代表了一个方法，它的定义是：&lt;/p&gt;&lt;div&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; System&lt;br /&gt;{ &lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;　　//&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt; 摘要: &lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;表示定义一组条件并确定指定对象是否符合这些条件的方法。&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;　　//&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt; 参数: &lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;　　//&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt; obj: &lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;要按照由此委托表示的方法中定义的条件进行比较的对象。&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;　　//&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt; 类型参数: &lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;　　//&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt; T: &lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;要比较的对象的类型。 &lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&lt;br /&gt;　　//&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt; 返回结果: &lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;　　//&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt; 如果 obj 符合由此委托表示的方法中定义的条件，则为 true；否则为 false。&lt;/span&gt;&lt;span style=&quot;color: #008000&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;delegate&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt; Predicate&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000&quot;&gt;(T obj);&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;这个委托常被好多Array , List&amp;lt;T&amp;gt; 类的方法所使用，用来查找集合中的元素。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;关于 Predicate,,跟 Action&amp;nbsp; 的进一步使用，可以参考 Adil Akhter 的博文 ：&lt;span style=&quot;color: #0000ff&quot;&gt;&lt;a href=&quot;http://weblogs.asp.net/adilakhter/archive/2008/04/16/using-predicate-amp-action-of-net2-0.aspx&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;&lt;font color=&quot;#0066cc&quot;&gt;Using Predicate &amp;amp; Action of .Net2.0&lt;/font&gt;&lt;/u&gt;&lt;/a&gt;&lt;/span&gt; 。我看的时候简单翻译了一下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;“自从我开始做软件开发以来，我就得一次又一次得面对这样的情况：不得不遍历整个集合然后对每个元素做一些处理，或者根据某一个逻辑规则来筛选出一些元素。一次从一次地写那些循环语句真是太讨厌了。&lt;/p&gt;&lt;p&gt;.NET 2.0 解决了这个问题，我们只需要告诉集合如何筛选，如何处理每个元素，然后它自己会处理重复的步骤。让我们来看一下System.Collections.Generic命名空间中的List&amp;lt;T&amp;gt;类，看看它提供了哪些支持：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.0734link.com/Attach/month_1102/lpe352_140610_3.png&quot; target=&quot;_blank&quot;&gt;&lt;img style=&quot;border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://blog.0734link.com/Attach/month_1102/cemdog_140614_4.png&quot; width=&quot;219&quot; height=&quot;788&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;有大量的针对 查询，排序，筛选的支持方法。如果我们看一下我们经常说到的 FindAll 跟 ForEach :&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; FindAll(&lt;span style=&quot;color: #2b91af&quot;&gt;Predicate&lt;/span&gt;&amp;lt;T&amp;gt; match);&lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;ForEach(&lt;span style=&quot;color: #2b91af&quot;&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action);&lt;/pre&gt;&lt;p&gt;会看到这儿的 Predicate 跟 Actor 是两个泛型委托，它们提供了一种方法，可以让我们灵活地对List中的每一个元素进行筛选或者执行某些处理。&lt;br /&gt;让我们深入观察一下这两个委托：&lt;/p&gt;&lt;h5&gt;Inside Predicate:&lt;/h5&gt;&lt;p&gt;Predicate 是一个泛型委托，它利用了.NET 2.0提供的泛型特性。它的定义是：&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;color: blue&quot;&gt;delegate bool &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Predicate&lt;/span&gt;&amp;lt;T&amp;gt;(T obj)&lt;/pre&gt;&lt;p&gt;如MSDN所定义, &lt;b&gt;Predicate&lt;/b&gt; -&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&amp;quot;represents a method that defines a set of criteria and determines whether the specific object meets this criteria.&amp;quot;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;简单地说，Predicate就是一个代表了接受一个T类型的参数，然后检查它是否满足某一规则然后返回 true 或者 false 的委托。示例如下：&lt;/p&gt;&lt;p&gt;在这个例子中，我们使用Predicate 来告诉集合如何筛选，然后集合会处理整个重复筛选的过程。&lt;/p&gt;&lt;p&gt;比如说，我们有一个 SprintBacklogItem 集合，想根据State==Closed 这一规则来进行筛选。我们就可以使用如下的一个方法：&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;color: blue&quot;&gt;　　　private bool &lt;/span&gt;HasStateClosed(&lt;span style=&quot;color: #2b91af&quot;&gt;SprintBacklogItem &lt;/span&gt;item) &lt;br /&gt;        { &lt;br /&gt;&lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(item.State == &lt;span style=&quot;color: #2b91af&quot;&gt;SprintBackLogStatesStrings&lt;/span&gt;.CLOSED) &lt;br /&gt;&lt;span style=&quot;color: blue&quot;&gt;return true&lt;/span&gt;; &lt;br /&gt;&lt;span style=&quot;color: blue&quot;&gt;return false&lt;/span&gt;; &lt;br /&gt;        }&lt;/pre&gt;&lt;p&gt;这个方法简单地检查了是否SprintBacklogItem&apos;s state is closed，然后返回true/false。现在如果我们观察一下这个方法的定义，就能够确认可以使用Predicate 委托来代表这个方法。下面这行代码就用 FindAll( ) 方法筛选出了所以关闭了的SprintBacklogItems&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;List&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;SprintBacklogItem&lt;/span&gt;&amp;gt; closedItems= _SprintBackLogsItems.FindAll(HasStateClosed);&lt;/pre&gt;&lt;h5&gt;Inside Action:&lt;/h5&gt;&lt;p&gt;类似于 Predicate,&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&amp;quot;Action is also one kind of generic delegate which represents a method that take the object as input and perform some operation on that.&amp;quot;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;定义：&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;color: blue&quot;&gt;delegate void &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt;(T obj);&lt;/pre&gt;&lt;p&gt;从这个委托的定义来看，它可以代表一种接受一个T类型的参数，然后什么也不返回的方法。&lt;/p&gt;&lt;p&gt;在List&amp;lt;T&amp;gt;中，由Action委托所代表的方法接受一个输入 obj 对象，然后对它进行处理。&lt;/p&gt;&lt;h6&gt;Example&lt;/h6&gt;&lt;p&gt;在这个例子中，我们将使用Action 对List中的每一个元素进行一个定义好的操作（initializing ActualHour = 10）&lt;/p&gt;&lt;p&gt;1. Define the method that will be represented by Action -&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;color: blue&quot;&gt;　　　public void &lt;/span&gt;InitActualHour(&lt;span style=&quot;color: #2b91af&quot;&gt;SprintBacklogItem &lt;/span&gt;item) &lt;br /&gt;        { &lt;br /&gt;            item.ActualHour = 10; &lt;br /&gt;        }&lt;/pre&gt;&lt;p&gt;2. Following line of code initialize all the elements&apos; Actual hour to 10 of the List -&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;color: blue&quot;&gt;this&lt;/span&gt;.ForEach(InitActualHour);&lt;/pre&gt;&lt;p&gt;是不是很COOL很便捷呀？ 为了不直接给Actor 以及 Predicate 定义方法，我们可以使用匿名方法处理委托。日后会讲到。今天先到这儿”&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;好了，Predicate 跟 Action 搞明白了，回到主题，接着看集合查询：&lt;/p&gt;&lt;p&gt;前面使用了这样的代码进行了筛选并输出结果，&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Predicate&amp;lt;Product&amp;gt; test = delegate(Product p) { return p.Price &amp;gt; 10m; };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;Product&amp;gt; matches = ProductSample.FindAll(test);&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Action&amp;lt;Product&amp;gt; print = delegate(Product p) { Console.WriteLine(p); };&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; matches.ForEach(print);&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;其实这两句可以合并成一句：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;ProductSample.FindAll(delegate (Product p){return p.Price&amp;gt;10m;}).ForEach(delegate (Product p){Console.WriteLine(p);});&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;是不是很简洁呀，呵呵。当然从来都是没有最XX，只有更XX，看下面的，LAMBDA出场！！！！！：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;ProductSample.FindAll(p=&amp;gt; p.Price &amp;gt; 10m).ForEach(p=&amp;gt;Console.WriteLine(p));&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;爽吧。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;爽的方法还不止一种，还可以这样爽：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(Product tmp in ProductSample.Where(p=&amp;gt;p.Price &amp;gt; 10m))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(tmp);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注意这个针对List&amp;lt;T&amp;gt;的 Where() 方法，呀呀呀，，，还有上一节的 OrderBy() 真是把能一般情况都考虑到了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;但是，有些人觉得那么写还不够爽，在C# 3.0中就弄出了个LINQ。。。。。这个内容就多了。。。日后再说。。。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</description>
		<guid>http://blog.0734link.com/Article/665.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/665/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/665.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/665/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/656.aspx</link>
		<title>NET多线程同步方法详解(三)：读写锁（ReadWriteLock)</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Wed, 09 Feb 2011 09:49:44 GMT</pubDate>
		<description>&lt;p&gt;读写锁的出现主要是在很多情况下，我们读资源的操作要多于写资源的操作。但是如果每次只对资源赋予一个线程的访问权限显然是低效的，读写锁的优势是同时可以有多个线程对同一资源进行读操作。因此在读操作比写操作多很多，并且写操作的时间很短的情况下使用读写锁是比较有效率的。读写锁是一个非静态类所以你在使用前需要先声明一个读写锁对象：&lt;/p&gt;&lt;p&gt;static private ReaderWriterLock _rwlock = new ReaderWriterLock();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 读写锁是通过调用AcquireReaderLock，ReleaseReaderLock，AcquireWriterLock，ReleaseWriterLock来完成读锁和写锁控制的 &lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static public void ReaderThread(int thrdId) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { // 请求读锁，如果100ms超时退出 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rwlock.AcquireReaderLock(10); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int inx = _rand.Next(_list.Count); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (inx &amp;lt; _list.Count) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;{0}thread {1}&amp;quot;, thrdId, _list[inx]); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rwlock.ReleaseReaderLock(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (ApplicationException) // 如果请求读锁失败 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;{0}thread get reader lock out time!&amp;quot;, thrdId); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static public void WriterThread() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 请求写锁 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rwlock.AcquireWriterLock(100); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string val = _rand.Next(200).ToString(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _list.Add(val); // 写入资源 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;writer thread has written {0}&amp;quot;, val); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { // 释放写锁 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rwlock.ReleaseWriterLock(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (ApplicationException) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Get writer thread lock out time!&amp;quot;); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果你想在读的时候插入写操作请使用UpgradeToWriterLock和DowngradeFromWriterLock来进行操作，而不是释放读锁。&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static private void UpgradeAndDowngrade(int thrdId) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rwlock.AcquireReaderLock(10); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 提升读锁到写锁 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LockCookie lc = _rwlock.UpgradeToWriterLock(100);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string val = _rand.Next(500).ToString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _list.Add(val); Console.WriteLine(&amp;quot;Upgrade Thread{0} add {1}&amp;quot;, thrdId, val); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { // 下降写锁 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rwlock.DowngradeFromWriterLock(ref lc); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (ApplicationException)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;{0}thread upgrade reader lock failed!&amp;quot;, thrdId); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 释放原来的读锁 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rwlock.ReleaseReaderLock();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (ApplicationException) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;{0}thread get reader lock out time!&amp;quot;, thrdId);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里有一点要注意的就是读锁和写锁的超时等待时间间隔的设置。通常情况下设置写锁的等待超时要比读锁的长，否则会经常发生写锁等待失败的情况。&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/656.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/656/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/656.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/656/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/655.aspx</link>
		<title>NET多线程同步方法详解(二)：互斥锁(lock)</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Wed, 09 Feb 2011 09:48:47 GMT</pubDate>
		<description>&lt;p&gt;lock关键字是实现线程同步的比较简单的方式，其实就是设置一个临界区。在lock之后的{...}区块为一个临界区，当进入临界区时加互斥锁，离开临界区时释放互斥锁。MSDN对lock关键字的描述是: lock 关键字可将语句块标记为临界区，方法是获取给定对象的互斥锁，执行语句，然后释放该锁。 &lt;br /&gt;具体例子如下:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static public void ThreadFunc(object name)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string str = name as string;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Random rand = new Random();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int count = rand.Next(100, 200);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; count; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lock (NumList)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NumList.Add(i);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;{0} {1}&amp;quot;, str, i);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp; 对lock的使用有几点建议：对实例锁定lock(this),对静态变量锁定lock(typeof(val))。lock的对象访问权限最好是private，否则会出现失去访问控制现象。&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/655.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/655/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/655.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/655/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/654.aspx</link>
		<title>NET多线程同步方法详解(一)：自由锁(InterLocked)</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Wed, 09 Feb 2011 07:27:47 GMT</pubDate>
		<description>&lt;p&gt;&amp;nbsp;本文主要描述在C#中线程同步的方法。线程的基本概念网上资料也很多就不再赘述了。直接接入主题，在多线程开发的应用中，线程同步是不可避免的。在.Net框架中，实现线程同步主要通过以下的几种方式来实现，在MSDN的线程指南中已经讲了几种，本文结合作者实际中用到的方式一起说明一下。&lt;/p&gt;&lt;p&gt;1. 维护自由锁(InterLocked)实现同步 &lt;br /&gt;2. 监视器（Monitor）和互斥锁（lock） &lt;br /&gt;3. 读写锁（ReadWriteLock) &lt;br /&gt;4. 系统内核对象 &lt;br /&gt;1) 互斥(Mutex), 信号量(Semaphore), 事件(AutoResetEvent/ManualResetEvent) &lt;br /&gt;2) 线程池&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 除了以上的这些对象之外实现线程同步的还可以使用Thread.Join方法。这种方法比较简单，当你在第一个线程运行时想等待第二个线程执行结果，那么你可以让第二个线程Join进来就可以了。 &lt;/p&gt;&lt;p&gt;自由锁(InterLocked)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对一个32位的整型数进行递增和递减操作来实现锁，有人会问为什么不用++或--来操作。因为在多线程中对锁进行操作必须是原子的，而++和--不具备这个能力。InterLocked类还提供了两个另外的函数Exchange, CompareExchange用于实现交换和比较交换。Exchange操作会将新值设置到变量中并返回变量的原来值: int oVal = InterLocked.Exchange(ref val, 1)。&lt;/p&gt;&lt;p&gt;监视器(Monitor)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在MSDN中对Monitor的描述是: Monitor 类通过向单个线程授予对象锁来控制对对象的访问。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Monitor类是一个静态类因此你不能通过实例化来得到类的对象。Monitor的成员可以查看MSDN，基本上Monitor的效果和lock是一样的，通过加锁操作Enter设置临界区，完成操作后使用Exit操作来释放对象锁。不过相对来说Monitor的功能更强，Moniter可以进行测试锁的状态，因此你可以控制对临界区的访问选择，等待or离开, 而且Monitor还可以在释放锁之前通知指定的对象，更重要的是使用Monitor可以跨越方法来操作。Monitor提供的方法很少就只有获取锁的方法Enter, TryEnter；释放锁的方法Wait, Exit；还有消息通知方法Pulse, PulseAll。经典的Monitor操作是这样的：&lt;br /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 通监视器来创建临界区 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static public void DelUser(string name)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 等待线程进入 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Monitor.Enter(Names);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Names.Remove(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Del: {0}&amp;quot;, Names.Count);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Monitor.Pulse(Names);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 释放对象锁 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Monitor.Exit(Names);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp; 其中Names是一个List&amp;lt;string&amp;gt;, 这里有一个小技巧，如果你想声明整个方法为线程同步可以使用方法属性：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 通过属性设置整个方法为临界区 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [MethodImpl(MethodImplOptions.Synchronized)] &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static public void AddUser(string name) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Names.Add(name); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Add: {0}&amp;quot;,Names.Count); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; 对于Monitor的使用有一个方法是比较诡异的，那就是Wait方法。在MSDN中对Wait的描述是: 释放对象上的锁以便允许其他线程锁定和访问该对象。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里提到的是先释放锁，那么显然我们需要先得到锁，否则调用Wait会出现异常，所以我们必须在Wait前面调用Enter方法或其他获取锁的方法，如lock，这点很重要。对应Enter方法，Monitor给出来另一种实现TryEnter。这两种方法的主要区别在于是否阻塞当前线程，Enter方法在获取不到锁时，会阻塞当前线程直到得到锁。不过缺点是如果永远得不到锁那么程序就会进入死锁状态。我们可以采用Wait来解决，在调用Wait时加入超时时限就可以。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Monitor.TryEnter(Names))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Monitor.Wait(Names, 1000); // !! &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Names.Remove(name); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Del: {0}&amp;quot;, Names.Count);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Monitor.Pulse(Names); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/654.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/654/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/654.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/654/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/649.aspx</link>
		<title>C#中的浅拷贝和深拷贝以及利用序列化等多种方式实现深拷贝</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Sun, 30 Jan 2011 15:25:00 GMT</pubDate>
		<description>&lt;p&gt;&lt;strong&gt;引言&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;background-color: #ffff66; color: black&quot;&gt;C#&lt;/b&gt;中有两种类型变量，一种 是值类型变量，一种是引用类型变量,对于值类型变量，&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;和前拷贝都是通过赋值操作符号(=)实现，其效果一致，将对象中的值类型的字段拷贝到新的对象中.这个很容易理解。 本文重点讨论引用类型变量的拷贝机制和实现。&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;background-color: #ffff66; color: black&quot;&gt;C#&lt;/b&gt;中引用类型对象的copy操作有两种：&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;(影子克隆/shallow copy):只复制对象的值类型字段,对象的引用类型,仍属于原来的引用. &lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;(深度克隆):不仅复制对象的值类型字段,同时也复制原对象中的对象.就是说完全是新对象产生的.&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;和&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;之间的区别：&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;是指将对象中的数值类型的字段拷贝到新的对象中，而对象中的引用型字段则指复制它的一个引用到目标对象。&lt;/p&gt;&lt;p&gt;　　注意：string类型有点特殊，对于&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;，类值类型对象进行处理。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;的实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;　　使用Object类MemberwiseClone实现&lt;/p&gt;&lt;p&gt;　　MemberwiseClone:创建当前 Object 的浅表副本。&lt;/p&gt;&lt;p&gt;　　MemberwiseClone 方法创建一个浅表副本，方法是创建一个新对象，然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的，则对该字段执行逐位复制。如果字段是引用类型，则复制引用但不复制引用的对象;因此，原始对象及其复本引用同一对象。&lt;/p&gt;&lt;p&gt;　　代码实现如下：&lt;/p&gt;&lt;p&gt;&lt;table style=&quot;border-bottom: #cccccc 1px dotted; border-left: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-right: #cccccc 1px dotted&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; width=&quot;95%&quot; align=&quot;center&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;word-wrap: break-word&quot; bgcolor=&quot;#f3f3f3&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public&amp;nbsp;class&amp;nbsp;Person &lt;br /&gt;　　{ &lt;br /&gt;　　public&amp;nbsp;int&amp;nbsp;Age&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;Address&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;Name&amp;nbsp;Name&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;object&amp;nbsp;Clone() &lt;br /&gt;　　{ &lt;br /&gt;　　return&amp;nbsp;this.MemberwiseClone(); &lt;br /&gt;　　} &lt;br /&gt;　　} &lt;br /&gt;　　public&amp;nbsp;class&amp;nbsp;Name &lt;br /&gt;　　{ &lt;br /&gt;　　public&amp;nbsp;Name(string&amp;nbsp;frisName,string&amp;nbsp;lastName) &lt;br /&gt;　　{ &lt;br /&gt;　　FristName&amp;nbsp;=&amp;nbsp;frisName; &lt;br /&gt;　　LastName&amp;nbsp;=&amp;nbsp;lastName; &lt;br /&gt;　　} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;FristName&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;LastName&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 赋值操作(=)VS使用Object类MemberwiseClone实现&lt;/p&gt;&lt;p&gt;　　对于引用类型的变量，我们有种误解，认为赋值操作就是&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;一种，其实不然，两者有区别。&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;(shallow copy)对于引用类型对象中的值类型字段进行了逐位复制。赋值运算符只是把源对象的引用赋值给目的对象，两者引用同一个对象。 &lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;后的对象的值类型字段更改不会反映到源对象，而赋值运算后的对象的值类型字段更改会反映到源对象 代码实现如下：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;table style=&quot;border-bottom: #cccccc 1px dotted; border-left: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-right: #cccccc 1px dotted&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; width=&quot;95%&quot; align=&quot;center&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;word-wrap: break-word&quot; bgcolor=&quot;#f3f3f3&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public&amp;nbsp;class&amp;nbsp;Person &lt;br /&gt;　　{ &lt;br /&gt;　　public&amp;nbsp;int&amp;nbsp;Age&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;Address&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;Name&amp;nbsp;Name&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　} &lt;br /&gt;　　public&amp;nbsp;class&amp;nbsp;Name &lt;br /&gt;　　{ &lt;br /&gt;　　public&amp;nbsp;Name(string&amp;nbsp;frisName,string&amp;nbsp;lastName) &lt;br /&gt;　　{ &lt;br /&gt;　　FristName&amp;nbsp;=&amp;nbsp;frisName; &lt;br /&gt;　　LastName&amp;nbsp;=&amp;nbsp;lastName; &lt;br /&gt;　　} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;FristName&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;LastName&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;　　相对于&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;,是指依照源对象为原型，创建一个新对象，将当前对象的所有字段进行执行逐位复制并支持递归，不管是是值类型还是引用类型，不管是静态字段还是非静态字段。&lt;/p&gt;&lt;p&gt;　　在&lt;b style=&quot;background-color: #ffff66; color: black&quot;&gt;C#&lt;/b&gt;中，我们们有三种方法实现&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;&lt;/p&gt;&lt;p&gt;　　实现ICloneable接口，自定义拷贝功能。&lt;/p&gt;&lt;p&gt;　　ICloneable 接口，支持克隆，即用与现有实例相同的值创建类的新实例。&lt;/p&gt;&lt;p&gt;　　ICloneable 接口包含一个成员 Clone，它用于支持除 MemberwiseClone 所提供的克隆之外的克隆。Clone 既可作为深层副本实现，也可作为浅表副本实现。在深层副本中，所有的对象都是重复的;而在浅表副本中，只有顶级对象是重复的，并且顶级以下的对象包含引用。 结果克隆必须与原始实例具有相同的类型或是原始实例的兼容类型。&lt;/p&gt;&lt;p&gt;　　代码实现如下：&lt;/p&gt;&lt;p&gt;&lt;table style=&quot;border-bottom: #cccccc 1px dotted; border-left: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-right: #cccccc 1px dotted&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; width=&quot;95%&quot; align=&quot;center&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;word-wrap: break-word&quot; bgcolor=&quot;#f3f3f3&quot;&gt;&lt;br /&gt;　Code &lt;br /&gt;　　public&amp;nbsp;class&amp;nbsp;Person:ICloneable &lt;br /&gt;　　{ &lt;br /&gt;　　public&amp;nbsp;int&amp;nbsp;Age&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;Address&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;Name&amp;nbsp;Name&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;object&amp;nbsp;Clone() &lt;br /&gt;　　{ &lt;br /&gt;　　Person&amp;nbsp;tem&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Person(); &lt;br /&gt;　　tem.Address&amp;nbsp;=&amp;nbsp;this.Address; &lt;br /&gt;　　tem.Age&amp;nbsp;=&amp;nbsp;this.Age; &lt;br /&gt;　　tem.Name&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Name(this.Name.FristName,&amp;nbsp;this.Name.LastName); &lt;br /&gt;　　return&amp;nbsp;tem; &lt;br /&gt;　　} &lt;br /&gt;　　} &lt;br /&gt;　　public&amp;nbsp;class&amp;nbsp;Name &lt;br /&gt;　　{ &lt;br /&gt;　　public&amp;nbsp;Name(string&amp;nbsp;frisName,&amp;nbsp;string&amp;nbsp;lastName) &lt;br /&gt;　　{ &lt;br /&gt;　　FristName&amp;nbsp;=&amp;nbsp;frisName; &lt;br /&gt;　　LastName&amp;nbsp;=&amp;nbsp;lastName; &lt;br /&gt;　　} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;FristName&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;LastName&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;　　大家可以看到,Person类继承了接口ICloneable并手动实现了其Clone方法,这是个简单的类,试想一下,如果你的类有成千上万个引用类型成员(当然太夸张,几十个还是有的)，这是不是份很恐怖的劳力活?&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;/反&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;类实现&lt;/p&gt;&lt;p&gt;　　不知道你有没有注意到DataSet对象,对于他提供的两个方法:&lt;/p&gt;&lt;p&gt;　　DataSet.Clone 方法，复制 DataSet 的结构，包括所有 DataTable 架构、关系和约束。不要复制任何数据。&lt;/p&gt;&lt;p&gt;　　新 DataSet，其架构与当前 DataSet 的架构相同，但是不包含任何数据。注意 如果已创建这些类的子类，则复本也将属于相同的子类。&lt;/p&gt;&lt;p&gt;　　DataSet.Copy 方法复制该 DataSet 的结构和数据.&lt;/p&gt;&lt;p&gt;　　新的 DataSet，具有与该 DataSet 相同的结构(表架构、关系和约束)和数据。注意如果已创建这些类的子类，则副本也将属于相同的子类。&lt;/p&gt;&lt;p&gt;　　好像既不是&lt;b style=&quot;background-color: #ff9999; color: black&quot;&gt;浅拷贝&lt;/b&gt;,又不是&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;，是不是很失望?但是两个结合起来不是我们要的&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;吗?看看DataSet的实现，注意&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;接口：ISerializable&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;是将对象或对象图形转换为线性字节序列，以存储或传输到另一个位置的过程。&lt;/p&gt;&lt;p&gt;　　反&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;是接受存储的信息并利用它重新创建对象的过程。&lt;/p&gt;&lt;p&gt;　　通过 ISerializable 接口，类可以执行其自己的&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;行为。&lt;/p&gt;&lt;p&gt;　　转换为线性字节序列后并利用其重新创建对象的过程是不是和我们的&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;的语意“逐位复制”很相像?&lt;/p&gt;&lt;p&gt;　　代码实现如下：&lt;/p&gt;&lt;p&gt;&lt;table style=&quot;border-bottom: #cccccc 1px dotted; border-left: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-right: #cccccc 1px dotted&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; width=&quot;95%&quot; align=&quot;center&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;word-wrap: break-word&quot; bgcolor=&quot;#f3f3f3&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Serializable] &lt;br /&gt;　　public&amp;nbsp;class&amp;nbsp;Person&amp;nbsp;:&amp;nbsp;ICloneable &lt;br /&gt;　　{ &lt;br /&gt;　　public&amp;nbsp;int&amp;nbsp;Age&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;Address&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;Name&amp;nbsp;Name&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;object&amp;nbsp;Clone() &lt;br /&gt;　　{ &lt;br /&gt;　　using&amp;nbsp;(MemoryStream&amp;nbsp;ms&amp;nbsp;=&amp;nbsp;new&amp;nbsp;MemoryStream(1000)) &lt;br /&gt;　　{ &lt;br /&gt;　　object&amp;nbsp;CloneObject; &lt;br /&gt;　　BinaryFormatter&amp;nbsp;bf&amp;nbsp;=&amp;nbsp;new&amp;nbsp;BinaryFormatter(null,&amp;nbsp;new&amp;nbsp;StreamingContext(StreamingContextStates.Clone)); &lt;br /&gt;　　bf.Serialize(ms,&amp;nbsp;this); &lt;br /&gt;　　ms.Seek(0,&amp;nbsp;SeekOrigin.Begin); &lt;br /&gt;　　//&amp;nbsp;反&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;至另一个对象(即创建了一个原对象的深表副本) &lt;br /&gt;　　CloneObject&amp;nbsp;=&amp;nbsp;bf.Deserialize(ms); &lt;br /&gt;　　//&amp;nbsp;关闭流 &lt;br /&gt;　　ms.Close(); &lt;br /&gt;　　return&amp;nbsp;CloneObject; &lt;br /&gt;　　} &lt;br /&gt;　　} &lt;br /&gt;　　} &lt;br /&gt;　　[Serializable] &lt;br /&gt;　　public&amp;nbsp;class&amp;nbsp;Name &lt;br /&gt;　　{ &lt;br /&gt;　　public&amp;nbsp;Name(string&amp;nbsp;frisName,&amp;nbsp;string&amp;nbsp;lastName) &lt;br /&gt;　　{ &lt;br /&gt;　　FristName&amp;nbsp;=&amp;nbsp;frisName; &lt;br /&gt;　　LastName&amp;nbsp;=&amp;nbsp;lastName; &lt;br /&gt;　　} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;FristName&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;LastName&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　} &lt;br /&gt;　　}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;　　注意：通过&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;和反&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;实现&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;，其和其字段类型必须标记为可&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;类型，既添加特性(Attribute)[Serializable]。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;　　通过反射实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;　　通过&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;/反&lt;b style=&quot;background-color: #880000; color: white&quot;&gt;序列化&lt;/b&gt;方式我们能比较流畅的实现&lt;b style=&quot;background-color: #a0ffff; color: black&quot;&gt;深拷贝&lt;/b&gt;，但是涉及到IO操作，托管的的环境中，IO操作比较消耗资源。 能不能有更优雅的解决方案。CreateInstance，对，利用反射特性。这个方法大家可以参考这篇博客：http://rubenhak.com/?p=70 文章反射类的Attribute，利用Activator.CreateInstance New一个类出来(有点像DataSet.Clone先获得架构)，然后利用PropertyInfo的SetValue和GetValue方法，遍历的方式进行值填充。&lt;/p&gt;&lt;p&gt;　　代码实现如下：&lt;/p&gt;&lt;p&gt;&lt;table style=&quot;border-bottom: #cccccc 1px dotted; border-left: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-right: #cccccc 1px dotted&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; width=&quot;95%&quot; align=&quot;center&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;word-wrap: break-word&quot; bgcolor=&quot;#f3f3f3&quot;&gt;&lt;br /&gt;　public&amp;nbsp;class&amp;nbsp;Person &lt;br /&gt;　　{ &lt;br /&gt;　　private&amp;nbsp;List&amp;nbsp;_friends&amp;nbsp;=&amp;nbsp;new&amp;nbsp;List(); &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;Firstname&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　public&amp;nbsp;string&amp;nbsp;Lastname&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　[Cloneable(CloneableState.Exclude)] &lt;br /&gt;　　[Cloneable(CloneableState.Include,&amp;nbsp;&amp;quot;Friends&amp;quot;)] &lt;br /&gt;　　public&amp;nbsp;List&amp;nbsp;Friends&amp;nbsp;{&amp;nbsp;get&amp;nbsp;{&amp;nbsp;return&amp;nbsp;_friends;&amp;nbsp;}&amp;nbsp;} &lt;br /&gt;　　[Cloneable(CloneableState.Exclude)] &lt;br /&gt;　　public&amp;nbsp;PersonManager&amp;nbsp;Manager&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;} &lt;br /&gt;　　}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/649.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/649/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/649.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/649/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/648.aspx</link>
		<title>利用序列化和反序列化实现深拷贝</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Sun, 30 Jan 2011 14:42:31 GMT</pubDate>
		<description>&lt;p&gt;假如说有一个简单的类，只有2个属性，那么可以用比较简单的方法实现深拷贝。&lt;/p&gt;&lt;pre&gt;&lt;ol class=&quot;dp-c&quot;&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&lt;span&gt;[Serializable] &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;Person &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;{ &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;&lt;span&gt;&amp;nbsp;Height&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;} &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;FirstName&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;} &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;} &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;Program&amp;nbsp;{ &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Main(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;string&lt;/span&gt;&lt;span&gt;[]&amp;nbsp;args)&amp;nbsp;{ &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//实例化一个对象 &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Person&amp;nbsp;PersonOne&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;Person(); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PersonOne.FirstName&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span&gt;; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PersonOne.Height&amp;nbsp;=&amp;nbsp;1; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//深拷贝 &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Person&amp;nbsp;DeepCopyPerson&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;Person(); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DeepCopyPerson.FirstName&amp;nbsp;=&amp;nbsp;PersonOne.FirstName; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DeepCopyPerson.Height&amp;nbsp;=&amp;nbsp;PersonOne.Height; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;}&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;代码中的DeepCopyPerson对象就是对PersonOne对象的一个深拷贝。其实还可以用序列化和反序列化的方法来实现对对象的深拷贝。Person类的[Serializable]属性是为了下面介绍序列化反序列化方法做深拷贝而做的准备，在这里没什么特别含义。&lt;/p&gt;&lt;div class=&quot;wp_syntax&quot;&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;ol class=&quot;dp-c&quot;&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;DeepCopy&amp;lt;t&amp;gt;(T&amp;nbsp;obj) &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;{ &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;retval; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;(MemoryStream&amp;nbsp;ms&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MemoryStream()) &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BinaryFormatter&amp;nbsp;bf&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;BinaryFormatter(); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//序列化成流 &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bf.Serialize(ms,&amp;nbsp;obj); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ms.Seek(0,&amp;nbsp;SeekOrigin.Begin); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//反序列化成对象 &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;retval&amp;nbsp;=&amp;nbsp;bf.Deserialize(ms); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ms.Close(); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T)retval; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;} &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;用的时候就是：&lt;/p&gt;&lt;div class=&quot;wp_syntax&quot;&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;ol class=&quot;dp-c&quot;&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;Program&amp;nbsp;{ &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Main(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;string&lt;/span&gt;&lt;span&gt;[]&amp;nbsp;args)&amp;nbsp;{ &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//实例化一个对象 &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Person&amp;nbsp;PersonOne&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;Person(); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PersonOne.FirstName&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span&gt;; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PersonOne.Height&amp;nbsp;=&amp;nbsp;1; &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//深拷贝 &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Person&amp;nbsp;DeepCopyPerson&amp;nbsp;=&amp;nbsp;DeepCopy&amp;lt;person&amp;gt;(PersonOne); &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;} &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;只要一个类被声明为可序列化的（就是带有[Serializable]标签），就可以用这个方法来进行深拷贝。记下来，免得以后自己忘记了。&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/648.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/648/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/648.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/648/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/639.aspx</link>
		<title>C# string.Format Method [C#字符串格式化方法]</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Tue, 25 Jan 2011 03:55:16 GMT</pubDate>
		<description>&lt;p&gt;You want to format strings in your C# program using the &lt;b&gt;string.Format&lt;/b&gt; method. The string.Format method is a static method that receives a string that specifies where the following arguments should be inserted, and these are called substitutions. Here we look at examples of the string.Format method in the C# language.&lt;/p&gt;&lt;h2&gt;Formatting multiple strings&lt;/h2&gt;&lt;p&gt;This example shows the use of the string.Format method to combine three strings with formatting options. The format string itself is the first argument to the string.Format method and it is specified as a string literal. The position markers in the format string are specified to the left of the colons, and this means the &amp;quot;0&amp;quot;, &amp;quot;1:&amp;quot;, and &amp;quot;2:&amp;quot; indicate where the first, second, and third arguments are inserted. The part after the &amp;quot;:&amp;quot; and in between the { } brackets indicates the exact format specification for that variable. &lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/string-literal&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See String Literal.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;border-bottom: navy 1px dashed; background: cyan&quot;&gt;--- Program that uses string.Format with three variables [C#] ---&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        &lt;font color=&quot;#008000&quot;&gt;//
        // Declare three variables that we will use in the format method.
        // ... The values they have are not important.
        //&lt;/font&gt;
        string value1 = &amp;quot;Dot Net Perls&amp;quot;;
        int value2 = 10000;
        DateTime value3 = new DateTime(2007, 11, 1);
        &lt;font color=&quot;#008000&quot;&gt;//
        // Use string.Format method with four arguments.
        // ... The first argument is the formatting string.
        // ... It specifies how the next three arguments are formatted.
        //&lt;/font&gt;
        string result = &lt;b&gt;&lt;u&gt;string.Format&lt;/u&gt;&lt;/b&gt;(&lt;span style=&quot;background: #ff0&quot;&gt;&amp;quot;{0}: {1:0.0} - {2:yyyy}&amp;quot;&lt;/span&gt;,
            value1,
            value2,
            value3);
        &lt;font color=&quot;#008000&quot;&gt;//
        // Write the result.
        //&lt;/font&gt;
        Console.WriteLine(result);
    }
}
&lt;b style=&quot;background: cyan&quot;&gt;--- Output of the program ---&lt;/b&gt;
Dot Net Perls: 10000.0 - 2007&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Walkthrough.&lt;/b&gt; There are three variables declared and initialized in the start of the Main method. These variables are used in the next call to string.Format. The first argument to the string.Format method is a format string. The resulting string contains extra formatting between the arguments. The &amp;quot;0.0&amp;quot; part of the format string specifies how the integer is displayed, while the &amp;quot;yyyy&amp;quot; part specifies that only the four-digit year of the date should be displayed.&lt;/p&gt;&lt;h2&gt;Number formats&lt;/h2&gt;&lt;p&gt;You can specify that a value type such as a double can be formatted inside the string.Format method based on the format string. The format string is the first argument to the string.Format method. The format string in this example uses the 0:0.0% syntax, which means that the second argument should be formatted with the pattern 0.0%. The arguments are numbered starting at zero.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;border-bottom: navy 1px dashed; background: cyan&quot;&gt;--- Program that uses string.Format with number [C#] ---&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        &lt;font color=&quot;#008000&quot;&gt;//
        // Format a ratio as a percentage string.
        // ... You must specify the percentage symbol in the format string.
        // ... It will multiply the value by 100 for you.
        //&lt;/font&gt;
        double ratio = 0.73;
        string result = &lt;b&gt;&lt;u&gt;string.Format&lt;/u&gt;&lt;/b&gt;(&lt;span style=&quot;background: #ff0&quot;&gt;&amp;quot;string = {0:0.0%}&amp;quot;&lt;/span&gt;,
            ratio);
        Console.WriteLine(result);
    }
}
&lt;b style=&quot;border-bottom: navy 1px dashed; background: cyan&quot;&gt;--- Output of the program ---&lt;/b&gt;
string = 73.0%&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Format string details.&lt;/b&gt; The format string here demonstrates several aspects to the string.Format method use. The 0.0% part of the format string specifies the exact number of digits that are required. Note that the 0.0% can have as many digits before the decimal place as necessary, but only one after the decimal place. The percentage symbol will result in the number being multiplied by 100 logically.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/0c899ak8(VS.71).aspx&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;Visit msdn.microsoft.com.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Padding&lt;/h2&gt;&lt;p&gt;Padding can be used with strings in the C# language and this can be expressed declaratively in formatting strings and the string.Format method. The term &apos;padding&apos; indicates that you are inserting a variable number of characters at the left or right of the string to ensure that the total length of the string is a fixed length. Instead of the PadLeft and PadRight methods, you can use the string.Format method with special substitutions.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/padleft&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See PadLeft String Method.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/padright&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See PadRight Aligns Strings.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;border-bottom: navy 1px dashed; background: cyan&quot;&gt;--- Program that uses string.Format for padding [C#] ---&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        &lt;font color=&quot;#008000&quot;&gt;//
        // The constant formatting string.
        // ... It specifies the padding using the comma and number syntax.
        // ... A negative number means to left-align.
        // ... A positive number means to right-align.
        //&lt;/font&gt;
        const string format = &lt;span style=&quot;background: #ff0&quot;&gt;&amp;quot;{0,-10} {1,10}&amp;quot;&lt;/span&gt;;
        &lt;font color=&quot;#008000&quot;&gt;//
        // Construct the strings.
        //&lt;/font&gt;
        string line1 = &lt;b&gt;&lt;u&gt;string.Format&lt;/u&gt;&lt;/b&gt;(format,
            100,
            5);
        string line2 = &lt;b&gt;&lt;u&gt;string.Format&lt;/u&gt;&lt;/b&gt;(format,
            &amp;quot;Carrot&amp;quot;,
            &amp;quot;Giraffe&amp;quot;);
        &lt;font color=&quot;#008000&quot;&gt;//
        // Write the formatted strings.
        //&lt;/font&gt;
        Console.WriteLine(line1);
        Console.WriteLine(line2);
    }
}
&lt;b style=&quot;border-bottom: navy 1px dashed; background: cyan&quot;&gt;--- Output of the program ---&lt;/b&gt;
100                 5
Carrot        Giraffe&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Description.&lt;/b&gt; For declaring padding inside a format string, use the comma character followed by the padding size. You can use a negative padding size to add padding to the right, which will left-align the text. You can use a positive padding size to add padding to the left, which will right-align the string.&lt;/p&gt;&lt;h2&gt;Dates&lt;/h2&gt;&lt;p&gt;The DateTime struct is a value type that is an abstract data type for any possible date and time. The string.Format method can be used with DateTime arguments and these will be inserted into the substitution markers. Because DateTime formatting is so important, this site introduces a thorough exploration of the string.Format and DateTime formatting strings.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/datetime-format&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#800080&quot;&gt;See DateTime Format Examples.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Filenames&lt;/h2&gt;&lt;p&gt;Many programs written in the C# language need to create files dynamically. The files often need to have file names that are based on the current date and time or another characteristic such as a counter. For example, a logging file can have a file name that is based on the exact date and time it was written. The string.Format method provides a way to express this functionality in a clear way. You can use the string.Format method with substitutions to create the filenames based on state variables.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/filename-datetime&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See DateTime for Filenames.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;StringBuilder (AppendFormat)&lt;/h2&gt;&lt;p&gt;The StringBuilder type presents a method called AppendFormat. The AppendFormat method receives a formatting string and also the arguments to the formatting string, which are placed in the substitution markers. For performance work, the AppendFormat method is not ideal; however, it can lead to clearer code.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/stringbuilder-1&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See StringBuilder Secrets.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Console.WriteLine formatting&lt;/h2&gt;&lt;p&gt;Console programs written in the C# language can use formatting strings directly inside the Console.Write and Console.WriteLine methods. When using Visual Studio, you can type Console.WriteLine and then scroll through the IntelliSense popup to find the overloads that receive the format string. You can then call Console.WriteLine with the same arguments as the string.Format method receives, and it will internally call the string.Format method.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/console-writeline&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See Console.WriteLine Use.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Implementation&lt;/h2&gt;&lt;p&gt;In the base class library, the string.Format method uses a param argument, which is a variable parameter list. This results in an array allocation on each invocation of the method. You can discover more about the params keyword here.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/params&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See Params Method.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Substitution processing.&lt;/b&gt; Internally, the string.Format method uses the StringBuilder type, which contains a mutable character buffer. It estimates a capacity based on a heuristic in the StringBuilder constructor. Next, the AppendFormat method is called to process the substitutions themselves. The ToString method is finally called; fortunately, the ToString method does not normally require a copy to be made.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/stringbuilder-capacity&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See StringBuilder Capacity Test.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Summary&lt;/h2&gt;&lt;p&gt;The string.Format method provides a way for you to insert argument strings and separators together, and also to specify display options for each argument individually. We saw how you can combine several strings and format dates, numbers, and percentages. We noted that many methods in the .NET Framework use this syntax. Finally, we delved into the implementation of the method itself.&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/639.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/639/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/639.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/639/Feeds.ashx</wfw:commentRss>
	</item>
	<item>
		<link>http://blog.0734link.com/Article/638.aspx</link>
		<title>C# DateTime Format Examples [C#日期格式化]</title>
		<author>329084470@qq.com()</author>
		<category>DotNet框架</category>
		<pubDate>Tue, 25 Jan 2011 03:54:01 GMT</pubDate>
		<description>&lt;p&gt;You need help with &lt;b&gt;DateTime formatting strings&lt;/b&gt; in the C# language or other .NET languages. The framework provides powerful formatting capabilities, but the syntax is confusing and there are some tricks. Here we see examples of using DateTime formats, and also the different values you can get with the individual formats.&lt;/p&gt;&lt;blockquote&gt;&lt;span style=&quot;background: beige&quot;&gt;&lt;b&gt;Format&lt;/b&gt; your DateTimes in the best way for your application.&lt;/span&gt;&lt;br /&gt;You will not have to write elaborate custom routines.&lt;br /&gt;The .NET Framework has a powerful DateTime format mechanism.&lt;/blockquote&gt;&lt;h2&gt;Using DateTime format string&lt;/h2&gt;&lt;p&gt;Here we see an example of how you can use a specific formatting string with DateTime and ToString to obtain a special DateTime string. This is useful when interacting with other systems, or when you require a precise format.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;background: #e6e6fa&quot;&gt;=== Program that uses DateTime format (C#) ===&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        DateTime time = DateTime.Now;              &lt;font color=&quot;#008000&quot;&gt;// Use current time&lt;/font&gt;
        string format = &amp;quot;MMM ddd d HH:mm yyyy&amp;quot;;    &lt;font color=&quot;#008000&quot;&gt;// Use this format&lt;/font&gt;
        Console.WriteLine(time.&lt;b&gt;ToString&lt;/b&gt;(format));  &lt;font color=&quot;#008000&quot;&gt;// Write to console&lt;/font&gt;
    }
}
&lt;b style=&quot;background: #e6e6fa&quot;&gt;=== Output of the program ===&lt;/b&gt;
Feb Fri 27 11:41 2009
&lt;b style=&quot;background: #e6e6fa&quot;&gt;=== Format string pattern ===&lt;/b&gt;
MMM     display three-letter month
ddd     display three-letter day of the WEEK
d       display day of the MONTH
HH      display two-digit hours on 24-hour scale
mm      display two-digit minutes
yyyy    display four-digit year&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Notes on the letters.&lt;/b&gt; The letters in the format string above specify the output you want to display. The final comment shows what the MMM, ddd, d, HH, mm, and yyyy will do.&lt;/p&gt;&lt;h2&gt;Modifying DateTime format string&lt;/h2&gt;&lt;p&gt;Here we see how you can modify the DateTime format string in the above example to get different output with ToString. We change some of the fields so the resulting value is shorter.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;background: #ffb6c1&quot;&gt;=== Program that uses different format (C#) ===&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        DateTime time = DateTime.Now;             &lt;font color=&quot;#008000&quot;&gt;// Use current time&lt;/font&gt;
        string format = &amp;quot;M d h:mm yy&amp;quot;;            &lt;font color=&quot;#008000&quot;&gt;// Use this format&lt;/font&gt;
        Console.WriteLine(time.&lt;b&gt;ToString&lt;/b&gt;(format)); &lt;font color=&quot;#008000&quot;&gt;// Write to console&lt;/font&gt;
    }
}
&lt;b style=&quot;background: #ffb6c1&quot;&gt;=== Output of the program ===&lt;/b&gt;
2 27 11:48 09
&lt;b style=&quot;background: #ffb6c1&quot;&gt;=== Format string pattern ===&lt;/b&gt;
M       display one-digit month number          [changed]
d       display one-digit day of the MONTH      [changed]
h       display one-digit hour on 12-hour scale [changed]
mm      display two-digit minutes
yy      display two-digit year                  [changed]&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Note on format string usages.&lt;/b&gt; You will also need to specify a format string when using DateTime.ParseExact and DateTime.ParseExact. This is because those methods require a custom pattern to parse.&lt;/p&gt;&lt;h2&gt;Single-letter DateTime format strings&lt;/h2&gt;&lt;p&gt;Here we see that you can use a single character with ToString or DateTime.ParseExact to specify a preset format available in the framework. These are standard formats and very useful in many programs. They can eliminate typos in the custom format strings.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;background: #b0c4de&quot;&gt;=== Program that tests formats (C#) ===&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        DateTime now = DateTime.Now;
        Console.WriteLine(now.ToString(&amp;quot;d&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;D&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;f&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;F&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;g&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;G&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;m&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;M&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;o&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;O&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;s&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;t&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;T&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;u&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;U&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;y&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;Y&amp;quot;));
    }
}
&lt;b style=&quot;background: #b0c4de&quot;&gt;=== Output of the program ===&lt;/b&gt;
d    2/27/2009
D    Friday, February 27, 2009
f    Friday, February 27, 2009 12:11 PM
F    Friday, February 27, 2009 12:12:22 PM
g    2/27/2009 12:12 PM
G    2/27/2009 12:12:22 PM
m    February 27
M    February 27
o    2009-02-27T12:12:22.1020000-08:00
O    2009-02-27T12:12:22.1020000-08:00
s    2009-02-27T12:12:22
t    12:12 PM
T    12:12:22 PM
u    2009-02-27 12:12:22Z
U    Friday, February 27, 2009 8:12:22 PM
y    February, 2009
Y    February, 2009&lt;/pre&gt;&lt;h2&gt;ToLongDateString and ToShortDateString&lt;/h2&gt;&lt;p&gt;Here we see the ToLongDateString, ToLongTimeString, ToShortDateString, and ToShortTimeString methods on DateTime. These methods are equivalent to the lowercase and uppercase D and T methods shown in the example above.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;background: #dcdcdc&quot;&gt;=== Program that uses ToString methods (C#) ===&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        DateTime now = DateTime.Now;
        Console.WriteLine(now.&lt;b&gt;ToLongDateString&lt;/b&gt;());  &lt;font color=&quot;#008000&quot;&gt;// Equivalent to D&lt;/font&gt;
        Console.WriteLine(now.&lt;b&gt;ToLongTimeString&lt;/b&gt;());  &lt;font color=&quot;#008000&quot;&gt;// Equivalent to T&lt;/font&gt;
        Console.WriteLine(now.&lt;b&gt;ToShortDateString&lt;/b&gt;()); &lt;font color=&quot;#008000&quot;&gt;// Equivalent to d&lt;/font&gt;
        Console.WriteLine(now.&lt;b&gt;ToShortTimeString&lt;/b&gt;()); &lt;font color=&quot;#008000&quot;&gt;// Equivalent to t&lt;/font&gt;
        Console.WriteLine(now.&lt;b&gt;ToString&lt;/b&gt;());
    }
}
&lt;b style=&quot;background: #dcdcdc&quot;&gt;=== Output of the program ===&lt;/b&gt;
ToLongDateString     Friday, February 27, 2009
ToLongTimeString     12:16:59 PM
ToShortDateString    2/27/2009
ToShortTimeString    12:16 PM
ToString             2/27/2009 12:16:59 PM&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Note on default ToString method.&lt;/b&gt; The default ToString method on DateTime shown above is equivalent to the simple &amp;quot;G&amp;quot; formatting string in the previous example. In other words, ToString(&amp;quot;G&amp;quot;) and ToString() do the same thing.&lt;/p&gt;&lt;h2&gt;Formatting characters&lt;/h2&gt;&lt;p&gt;When you use DateTime.ParseExact, or ToString(), you need to specify a formatting string, which is a sequence of characters that designate how the final result will look. What follows are the author&apos;s notes on the strings from MSDN.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/24-hour-military-time&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See 24-Hour and Military Time Formats.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;background: khaki&quot;&gt;d&lt;/span&gt;
Use this to specify the numeric value for the day of the month.
It will be one or two digits long.
&lt;span style=&quot;background: khaki&quot;&gt;dd&lt;/span&gt;
This is the same as a single d, except there are always two digits, with a leading
0 prepended if necessary.
&lt;span style=&quot;background: khaki&quot;&gt;ddd&lt;/span&gt;
This displays a three-letter string that indicates the current day of the week.
&lt;span style=&quot;background: khaki&quot;&gt;dddd&lt;/span&gt;
This displays the full string for the day of the week.
&lt;span style=&quot;background: khaki&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;ff&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;fff&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;ffff&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;fffff&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;ffffff&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;fffffff&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;F&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;FF&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;FFF&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;FFFF&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;FFFFF&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;FFFFFF&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;FFFFFFF&lt;/span&gt;
Use the lowercase f to indicate the seconds to one digit length.
Use two lowercase fs to indicate the seconds to two digits.
The uppercase F patterns do the same but work differently on trailing zeros.
&lt;span style=&quot;background: khaki&quot;&gt;gg&lt;/span&gt;
Use this to display A.D. on your date.
It is unlikely that this will be B.C. in most programs.
&lt;span style=&quot;background: khaki&quot;&gt;h&lt;/span&gt;
Display the hours in one digit if possible.
If the hours is greater than 9, it will display two digits.
Range is 1-12.
&lt;span style=&quot;background: khaki&quot;&gt;hh&lt;/span&gt;
Display the hours in two digits always, even if the hour is one digit.
The range here will be 01-12.
&lt;span style=&quot;background: khaki&quot;&gt;H&lt;/span&gt;
This represents the hours in a range of 0-23, which is called military time
in some parts of the world. [See next row for two digits and link.]
&lt;span style=&quot;background: khaki&quot;&gt;HH&lt;/span&gt;
This represents the hours in a range of 00-23.
The only different here between the single H is that there is always a leading zero
if the number is one digit.
&lt;span style=&quot;background: khaki&quot;&gt;K&lt;/span&gt;
Use this to display time zone information.
&lt;span style=&quot;background: khaki&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;mm&lt;/span&gt;
This formats the minutes in your date format string.
Here, the one m means that there is only one digit displayed if possible.
The two ms means that there are always two digits displayed, with a leading zero
if necessary.
&lt;span style=&quot;background: khaki&quot;&gt;M&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;MM&lt;/span&gt;
These display the months in numeric form.
The one uppercase M does not have a leading zero on it.
The two uppercase Ms will format a number with a leading zero if it is required.
&lt;span style=&quot;background: khaki&quot;&gt;MMM&lt;/span&gt;
This displays the abbreviated three-letter form of the month represented in
the DateTime.
&lt;span style=&quot;background: khaki&quot;&gt;MMMM&lt;/span&gt;
This displays the full month string, properly capitalized.
&lt;span style=&quot;background: khaki&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;ss&lt;/span&gt;
The lowercase s displays seconds.
A single lowercase s means that you do not require a leading zero.
Two lowercase s characters means you always want two digits, such as 00-59.
&lt;span style=&quot;background: khaki&quot;&gt;t&lt;/span&gt;
Use the lowercase t to indicate A, when the time is in the AM, and P, for when
the time is in PM.
&lt;span style=&quot;background: khaki&quot;&gt;tt&lt;/span&gt;
Use two lowercase tts to display the full AM or PM string.
You will normally want this for when you are displaying the string to a user.
&lt;span style=&quot;background: khaki&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;yy&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;yyy&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;yyyy&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;yyyyy&lt;/span&gt;
These display the year to different digits.
In your programs, you won&apos;t need three digits for the year, or five.
Therefore, you should only consider one y, two ys, or four ys.
&lt;span style=&quot;background: khaki&quot;&gt;z&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;zz&lt;/span&gt;&lt;span style=&quot;background: khaki&quot;&gt;zzz&lt;/span&gt;
These represent the offset from the UTC time on the local operating system.
&lt;span style=&quot;background: khaki&quot;&gt;:&lt;/span&gt;
This is the time separator.
&lt;span style=&quot;background: khaki&quot;&gt;/&lt;/span&gt;
This is the date separator.
&lt;span style=&quot;background: khaki&quot;&gt;Others&lt;/span&gt;
Most other characters will be printed to the output string without any modification.&lt;/pre&gt;&lt;h2&gt;Difference between d and dd, ddd and dddd&lt;/h2&gt;&lt;p&gt;It is important to note that d and dd (one and two ds) mean something entirely different than ddd and dddd (three and four ds). d and dd indicate the day of the month, while ddd and dddd indicate the day of the week, in a word. Please see the table above.&lt;/p&gt;&lt;h2&gt;Three-letter days&lt;/h2&gt;&lt;p&gt;In some systems it may be useful to display the day of the week in a three-letter form. Here we see a simple program that prints out the days of the week in three-letter format. This will vary based on the language installed on the computer.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;background: gold&quot;&gt;=== Program that tests days (C#) ===&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        DateTime now = DateTime.Today;
        for (int i = 0; i &amp;lt; 7; i++)
        {
            Console.WriteLine(now.&lt;b&gt;ToString&lt;/b&gt;(&amp;quot;ddd&amp;quot;));
            now = now.AddDays(1);
        }
    }
}
&lt;b style=&quot;background: gold&quot;&gt;=== Output of the program ===&lt;/b&gt;
Thu
Fri
Sat
Sun
Mon
Tue
Wed&lt;/pre&gt;&lt;h2&gt;Displaying complete day&lt;/h2&gt;&lt;p&gt;Often you need to display the complete day of the week in your C# code, and the four ds together will do this for you. This simple program shows all seven different day strings you can get from the dddd.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;background: #dcdcdc&quot;&gt;=== Program that shows day strings (C#) ===&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        DateTime now = DateTime.Today;
        for (int i = 0; i &amp;lt; 7; i++)
        {
            Console.WriteLine(now.&lt;b&gt;ToString&lt;/b&gt;(&amp;quot;dddd&amp;quot;));
            now = now.AddDays(1);
        }
    }
}
&lt;b style=&quot;background: #dcdcdc&quot;&gt;=== Output of the program ===&lt;/b&gt;
Thursday
Friday
Saturday
Sunday
Monday
Tuesday
Wednesday&lt;/pre&gt;&lt;h2&gt;Displaying the era&lt;/h2&gt;&lt;p&gt;The .NET platform allows you to display the date with the era or period, which is usually A.D. or B.C. It is unlikely that you will need to use B.C., except in a rare theoretical application. Nevertheless, here is what the two gs will print. Use the code &amp;quot;DateTime.Now.ToString(&amp;quot;gg&amp;quot;);&amp;quot;.&lt;/p&gt;&lt;h2&gt;Month property and strings&lt;/h2&gt;&lt;p&gt;You may need to display the month name in a three-letter format. This is equivalent, in English, to taking a substring of the first three letters, but using the three Ms next to each other may be easier and more terse for your code. Additionally, you may want full month strings. This site contains a useful article that covers DateTime month strings and the Month property in more detail.&lt;/p&gt;&lt;p class=&quot;l&quot;&gt;&lt;a href=&quot;http://dotnetperls.com/datetime-month&quot; target=&quot;_blank&quot;&gt;&lt;font color=&quot;#0066cc&quot;&gt;See DateTime.Month Property.&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Displaying AM/PM—first letter only&lt;/h2&gt;&lt;p&gt;This isn&apos;t something you are likely to need, but interesting to find out. When you specify one t, you can get the first letter of the AM or PM string. This is equivalent to using Substring or getting the first char of the tt string. There is a space at the end of the format string because the value &amp;quot;t&amp;quot; can mean something else in the format string.&lt;/p&gt;&lt;h2&gt;Displaying AM/PM—full string&lt;/h2&gt;&lt;p&gt;Here we see how you can get the string AM or PM in your DateTime ToString code. The code adds 12 to ensure the second iteration is in the other half.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;background: #87cefa&quot;&gt;=== Program that displays AM and PM (C#) ===&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        DateTime now = DateTime.Now;
        for (int i = 0; i &amp;lt; 2; i++)
        {
            Console.WriteLine(now.&lt;b&gt;ToString&lt;/b&gt;(&amp;quot;tt &amp;quot;));
            now = now.AddHours(12);
        }
    }
}
&lt;b style=&quot;background: #87cefa&quot;&gt;=== Output of the program ===&lt;/b&gt;
PM
AM&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Note on lack of periods.&lt;/b&gt; There are no periods in the output of tt in the example above. Therefore, if you require periods in your AM or PM, you would have to manipulate the string.&lt;/p&gt;&lt;h2&gt;Displaying year to different digits&lt;/h2&gt;&lt;p&gt;You can vary the number of digits displayed in the year string. You will always want to use y, yy, or yyyy for your programs. The framework accepts different numbers, but they are impractical in the real world. Occasionally two ys is useful for a user-oriented program, but for your back end code, you will want to use four ys. You do not need uppercase Ys.&lt;/p&gt;&lt;pre&gt;&lt;b style=&quot;background: gold&quot;&gt;=== Program that displays years (C#) ===&lt;/b&gt;
using System;
class Program
{
    static void Main()
    {
        DateTime now = DateTime.Now;
        Console.WriteLine(now.ToString(&amp;quot;y &amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;yy&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;yyy&amp;quot;));   &lt;font color=&quot;#008000&quot;&gt;// &amp;lt;-- Don&apos;t use this&lt;/font&gt;
        Console.WriteLine(now.ToString(&amp;quot;yyyy&amp;quot;));
        Console.WriteLine(now.ToString(&amp;quot;yyyyy&amp;quot;)); &lt;font color=&quot;#008000&quot;&gt;// &amp;lt;-- Don&apos;t use this&lt;/font&gt;
    }
}
&lt;b style=&quot;background: gold&quot;&gt;=== Output of the program ===&lt;/b&gt;
9
09
2009
2009
02009&lt;/pre&gt;&lt;h2&gt;Summary&lt;/h2&gt;&lt;p&gt;In this example set, we saw lots of information and examples regarding DateTime format strings. We covered single-letter preset format strings, and more complicated custom format strings with different character codes. We saw an overview of the custom code letters. Finally, we saw enumerations of all the values for days of the week, months, and also three-letter versions of those. More general examples that use the format string system in the .NET Framework are available.&lt;/p&gt;</description>
		<guid>http://blog.0734link.com/Article/638.aspx</guid>
		<trackback:ping>http://blog.0734link.com/Article/638/Trackback.ashx</trackback:ping>
		<comments>http://blog.0734link.com/Article/638.aspx#CommentPostAnchor</comments>
		<wfw:commentRss>http://blog.0734link.com/Article/638/Feeds.ashx</wfw:commentRss>
	</item>
</channel>
</rss>
