<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>CLR via C# on 冯威的博客</title><link>https://fwhyy.com/tags/clr-via-c%23/</link><description>Recent content in CLR via C# on 冯威的博客</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Thu, 16 Jul 2009 00:00:00 +0800</lastBuildDate><atom:link href="https://fwhyy.com/tags/clr-via-c%23/atom.xml" rel="self" type="application/rss+xml"/><item><title>CLR Via C# 学习笔记（6） 方法参数相关（out ref params）</title><link>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-6-the-method-parameters-related/</link><pubDate>Thu, 16 Jul 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-6-the-method-parameters-related/</guid><description>&lt;blockquote&gt;
&lt;p&gt;CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;通常我们在使用方法的时候，方法的参数是按值传递的，如果传递的参数是引用类型的对象，是将引用对象的地址传给方法。如果传递的是值类型实例，传递给方法的是该实例的一个副本。允许使用在方法中按引用来传递参数，C#中使用out和ref关键字来体现。下面就来介绍out和ref的使用。&lt;/p&gt;
&lt;h2 id="out"&gt;out&lt;/h2&gt;
&lt;p&gt;1 使用out时在方法的参数定义和方法的调用时都要用out关键字，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;static void Main(string[] args)
{
 string name = string.Empty;
 GetStr(out name); //调用时加out
 Console.WriteLine(name);
}
private static void GetStr(out string name) //方法参数定义时的out
{
 name = &amp;#34;oec2003&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 如果一个方法有out修饰的参数，在方法结束前必须给给参数赋值，否则不能通过编译，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;static void Main(string[] args)
{
 string name = &amp;#34;oec2003&amp;#34;;
 GetStr(out name);
 Console.WriteLine(name);
}
private static void GetStr(out string name)
{
 //没有给name赋值，编译时会出现“控制离开当前方法之前必须对
 //out 参数“name”赋值”异常
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3 在调用有out参数的方法时，没有必要给out参数赋初始值，因为赋的值不会传递到方法的内部，如果在方法的内部要强行使用out参数会有编译错误。代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;static void Main(string[] args)
{
 //给out参数name赋初始值oec2003
 string name = &amp;#34;oec2003&amp;#34;;
 GetStr(out name);
 Console.WriteLine(name);
}
private static void GetStr(out string name)
{
 name = &amp;#34;hello&amp;#34; + name;
 //name在调用前虽赋值为oec2003 ，
 //但此处会报错“使用了未赋值的 out 参数name”
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4 通常我们需要在一个方法中返回多个值的时候就可以使用out参数。&lt;/p&gt;
&lt;p&gt;5 如果两个方法的参数个数和类型都相同，区别只是其中一个为out参数，那么这两个方法是可以进行重载的，下面的代码可以正常运行。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private static void GetStr(out string name)
{
 name = &amp;#34;oec2003&amp;#34;;
}
private static void GetStr(string name)
{
 name = &amp;#34;oec2003&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="ref"&gt;ref&lt;/h2&gt;
&lt;p&gt;1 和out参数一样，使用ref时在方法的参数定义和方法的调用时都要用ref关键字。&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（5） 静态构造函数的性能</title><link>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-5-the-performance-of-the-static-constructor/</link><pubDate>Wed, 08 Jul 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-5-the-performance-of-the-static-constructor/</guid><description>&lt;blockquote&gt;
&lt;p&gt;CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在上一篇《CLR Via C# 学习笔记（4） 方法 构造函数 》中讲到了一些静态构造函数方面的知识，现在也回顾一下，大概总结如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;静态构造函数是私有的（private） ，而且不能人为去修改访问修饰符。&lt;/li&gt;
&lt;li&gt;静态构造函数不应该去调用基类的静态构造函数，因为静态字段不会被继承到子类。&lt;/li&gt;
&lt;li&gt;静态构造函数在一个类型中有且仅有一个，并且是无参的。&lt;/li&gt;
&lt;li&gt;静态构造函数中只能初始化静态字段。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;从上面的第一点可以知道静态构造函数都是private的，所以不能显示区进行调用，关于JIT何时会去生成调用静态构造函数的代码。存在着两种说法。通常被称为Precise和BeforeFieldInit。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Precise方式JIT编译器生成调用的时机：首次创建类型的代码之前；访问类的非继承字段或成员代码之前。&lt;/li&gt;
&lt;li&gt;BeforeFieldInit方式JIT编译器生成调用的时机：在访问费继承静态字段代码之前。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这两种方式的主要区别就是选择调用静态构造函数的时机是否是确定的，Precise方式CLR会在确定的时刻调用静态构造函数，而BeforeFieldInit方式CLR可以自由选择调用静态构造函数的时机，利用这一点，CLR可以根据类型是否在程序域中加载来选择静态构造函数的调用次数，以便能生成执行更快的代码。&lt;/p&gt;
&lt;p&gt;下面来看来个类分别展现了这两种方式&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public classUserPrecise
{
 public static string_name = &amp;#34;内联赋值：oec2003&amp;#34;;
 staticUserPrecise()
 {
 _name = &amp;#34;构造函数赋值：oec2003&amp;#34;;
 }
}
public classUserBeforeFieldInit
{
 public static string_name = &amp;#34;内联赋值：oec2003&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;通过IL代码可以看出在UserBeforeFieldInit 的元数据上有BeforeFieldInit的标记，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290802573.webp" alt="2010-12-29_173428" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;既然上面提到BeforeFieldInit方式CLR可以选择调用构造函数的次数从而来生成执行更快的代码，下面就写一段测试代码来看看究竟怎样。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Test1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Test2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Test1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UserBeforeFieldInit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Test1-UserBeforeFieldInit 用时：&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Elapsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UserPrecise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Test1-UserPrecise 用时：&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Elapsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Test2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UserBeforeFieldInit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Test2-UserBeforeFieldInit 用时：&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Elapsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UserPrecise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Test2-UserPrecise 用时：&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Elapsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserBeforeFieldInit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserPrecise&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;UserPrecise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;测试结果如下：&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（4） 方法 构造函数</title><link>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-5-methods-the-constructor/</link><pubDate>Fri, 03 Jul 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-5-methods-the-constructor/</guid><description>&lt;blockquote&gt;
&lt;p&gt;《CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;构造函数是可以将类型实例初始化为有效状态的特殊方法。构造函数在元数据中通常用.ctor来表示，通过IL代码可以看到。在创建一个类型的实例时，通常分为三步：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为实例的数据字段分配内存。&lt;/li&gt;
&lt;li&gt;创建对象指针和同步索引块。&lt;/li&gt;
&lt;li&gt;调用类型的实例构造器来设置对象的初始状态。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="引用类型的实例构造器"&gt;引用类型的实例构造器&lt;/h2&gt;
&lt;p&gt;在创建一个引用类型的对象是，调用类型的实例构造函数之前，会将对象分配的内存做清零处理，就是说在构造函数中没有显示赋值的所有字段都将设置为0或null。&lt;/p&gt;
&lt;p&gt;实例构造函数和一般方法不同，他永远都不能被继承，所有以下的关键字也不能用于实例构造函数（virtual new override sealed abstract）。&lt;/p&gt;
&lt;p&gt;一个类中如果没有显示定义任何构造函数，C#编译器将定义一个默认的无参构造函数。&lt;/p&gt;
&lt;p&gt;抽象（abstract）类的默认构造函数的访问修饰符为protected。&lt;/p&gt;
&lt;p&gt;构造函数可以初始化字段，不过在c#语言中提供了一种简单的方法，在定义字段的时候直接赋值以初始化。如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class User
{
 private int _age = 25;
 private string _name = &amp;#34;oec2003&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;像上面那样的确很方便，但如果有好几个已经初始化的实例字段和多个重载的构造函数同时存在的情况下，就应该将实例字段的初始化放到一个公共的构造函数中，其他的构造函数通过this来显示调用该构造函数，这样可以减少代码生成的大小，看下面的例子。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class User
{
 private int _age = 25;
 private string _name = &amp;#34;oec2003&amp;#34;;
 private string _email = &amp;#34;oec2003@gmail.com&amp;#34;;

 public User(Int32 age)
 {
 this._age = age;
 }

 public User(string name)
 {
 this._name = name;
 }

 public User(Int32 age, String name, String email)
 {
 this._age = age;
 this._name = name;
 this._email = email;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;正确的写法应该像下面这样&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class User
{
 private int _age;
 private string _name;
 private string _email;

 public User()
 {
 _age = 25;
 _name = &amp;#34;oec2003&amp;#34;;
 _email = &amp;#34;oec2003@gmail.com&amp;#34;;
 }

 public User(Int32 age)
 : this()
 {
 this._age = age;
 }

 public User(string name)
 : this()
 {
 this._name = name;
 }

 public User(Int32 age, String name, String email)
 : this()
 {
 this._age = age;
 this._name = name;
 this._email = email;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="值类型的实例构造函数"&gt;值类型的实例构造函数&lt;/h2&gt;
&lt;p&gt;值类型的实例构造函数和引用类型的有很大不同，在值类型中不能含有无参的构造函数，如果显式指定无参的构造函数将会出现编译错误。如下面代码会出现编译错误：&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（3） 常量和字段（const readonly）</title><link>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-3-constants-and-fields/</link><pubDate>Mon, 22 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-3-constants-and-fields/</guid><description>&lt;blockquote&gt;
&lt;p&gt;《CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;常量和字段都是类型的数据成员，但是区别却是很大的。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;常量的值永远不会改变。字段有多种类型，非只读字段的值是可以改变的。&lt;/li&gt;
&lt;li&gt;常量的值必须在编译时就确定，也就是说在定义时就要赋值。编译后常量的值就保存在程序集的元数据中；字段是存储在动态内存中，在运行时才能得到字段的值。&lt;/li&gt;
&lt;li&gt;常量的定义必须用基元类型，关于基元类型可以参考(CLR Via C# 学习笔记（1） 基元类型 值类型 引用类型 )；字段的定义可以是任何类型。&lt;/li&gt;
&lt;li&gt;因为常量的值不能改变，可以将其看做是静态类型，在IL代码中可以看到常量有static修饰符，所以在调用的时候和调用静态字段一样，直接用类名.常量名；字段中的静态字段的调用才和常量一样直接用类名.字段名，调用非静态字段必须用类的实例。、&lt;/li&gt;
&lt;li&gt;C#不允许使用static修饰常量，因为常量本身就隐含是static类型；字段可以使用static，使用static定义的字段为静态字段。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="下面看个例子来理解下常量"&gt;下面看个例子来理解下常量&lt;/h2&gt;
&lt;p&gt;1 创建一个类库项目命名为Oec2003ClassLibrary ,在默认的类Class1中写如下代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace Oec2003ClassLibrary
{
 public class Class1
 {
 public const double PI = 3.14;

 public static double _pi = 3.14;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 创建一个web项目，添加对Oec2003ClassLibrary类库项目的引用，新建页面ConstTest.aspx,在PageLoad中写如下代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;protected void Page_Load(object sender, EventArgs e)
{
 Response.Write(Class1.PI+&amp;#34;&amp;lt;br/&amp;gt;&amp;#34;);
 Response.Write(Class1._pi);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3 将ConstTest设为起始页，运行，可以看到结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290816263.webp" alt="2010-12-29_181713" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 现在将Oec2003ClassLibrary 项目中的Class1的代码改写如下，然后从新编译该项目。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace Oec2003ClassLibrary
{
 public class Class1
 {
 public const double PI = 3.1415926;
 public static double _pi = 3.1415926;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 刷新刚才的页面 ，可以看到结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290816174.webp" alt="2010-12-29_181748" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 从新运行ConstTest页面可以看到如下结果&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290816233.webp" alt="2010-12-29_181824" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;从上面的例子可以看出，在应用程序不从新编译的情况下，常量的值永远不会发生改变。如果应用程序想要获得常量的新值，就必须重新编译，所以在运行时一个应用程序集想获得另一个应用程序集中的值，则不能使用常量，可以使用只读字段（readonly）。&lt;/p&gt;
&lt;p&gt;字段也是一种类型的数据成员，字段的修饰符有 static readonly volatile，没有上述修饰修饰的字段为普通的实例字段。static可以和readonly一起使用，就是静态只读字段。有关volatile将在后面的部分介绍。&lt;/p&gt;
&lt;h2 id="关于readonly要注意的地方"&gt;关于readonly要注意的地方&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;当readonly修饰的字段为值类型时，在调用的时候如果视图去改变字段的值，将会编译出错。&lt;/li&gt;
&lt;li&gt;当readonly修饰的字段为引用类型时，调用时不能改变其引用，但可以改变应用对象的值，看下面的例子。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1 在Oec2003ClassLibrary项目的Class1.cs文件写如下代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace Oec2003ClassLibrary
{
 public class Class1
 {
 public const double PI = 3.14;
 public static readonly double _pi = 3.14;

 public static readonly User user = new User(&amp;#34;oec2003&amp;#34;);
 }
 public class User
 {
 public User(string name)
 {
 Name = name;
 }
 public string Name { get; set; }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 在web项目中添加页面，命名为Readonly.aspx，PageLoad代码如下&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（2） 装箱和拆箱</title><link>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-2-boxing-and-unboxing/</link><pubDate>Thu, 18 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-2-boxing-and-unboxing/</guid><description>&lt;blockquote&gt;
&lt;p&gt;CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;装箱和拆箱是已经被嚼烂的两个概念了，并且在一些面试中也经常考到。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;装箱：将值类型转换为引用类型。&lt;/li&gt;
&lt;li&gt;拆箱：将引用类型转换为值类型。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;值类型是一种相对轻型的类型，不像对象那样在托管堆中分配，也不会被GC，不通过指针来引用，不过在有些时候需要获取对值类型的引用，例如在使用net1.0的集合类ArrayList的时候。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ArrayList&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ArrayList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//因Point为值类型，分配在堆栈中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//初始化Point中的成员&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//对p进行装箱后，将引用添加到list中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ArrayList的Add方法是接受一个Object参数，如下&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;所以在执行Add方法时会将Point值类型转换为一个堆得托管对象，并获取到这个对象的引用，将引用地址存储在ArrayList中。&lt;/p&gt;
&lt;p&gt;在一个值类型装箱的时候内部发生的事情：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在托管堆分配好内存。分配的内存是值类型的各个字段所需内存量加上托管堆上的两个额外成员（类型对象指针和同步索引块）所需的内存量。&lt;/li&gt;
&lt;li&gt;值类型中的字段值复制到新分配的堆内存中。&lt;/li&gt;
&lt;li&gt;返回对象的引用地址。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;拆箱就是执行和装箱相反的操作，将引用类型转化为值类型。接上面的代码，获取ArrayList中的元素值用如下代码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="p"&gt;=(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;X:&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#34; Y:&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面的代码中通过索引取到ArrayList中存储的各个Point的引用地址，通过Point类型转换将其对应的值从堆中复制到Point的实例point中，这个转换的过程就是拆箱的过程。&lt;/p&gt;
&lt;p&gt;在拆箱的过程中要注意以下两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果对已装箱的值类型的引用的变量为null，会引发NullRefreenceException异常&lt;/li&gt;
&lt;li&gt;如果一个引用指向的对象在拆箱时不是用的装箱时所使用的类型，将会引发InvalidCastException异常。代码如下：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int16&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//引发InvalidCastException异常&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;正确的做法是，现将其用Int32类型来拆箱，然后再强制转换为Int16&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int16&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int16&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;下面来看两段程序来深入理解下装箱和拆箱&lt;/p&gt;
&lt;p&gt;代码一：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;, &amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面的代码中有多少次装箱呢？乍一看好像就一次（Object o=x；），其实一共有三次装箱，看看IL代码就一目了然了。&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（1） 基元类型 值类型 引用类型</title><link>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-1-primitive-types/</link><pubDate>Wed, 17 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-1-primitive-types/</guid><description>&lt;blockquote&gt;
&lt;p&gt;CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;首先了解下什么是基元类型，基元类型是编译器直接支持的数据类型，像我们平时经常用到的int string bool 都是基元类型，基元类型是映射到FCL中的类型，像前面的三种类型对应到FCL中就是Int32 String Boolean，基元类型只是给我们的编程提供了方便，它和FCL中的类型在编译后最终生成的IL完全相同。下面给出基元类型和FCL类型的对应表&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;C#基元类型&lt;/th&gt;
					&lt;th&gt;FCL类型&lt;/th&gt;
					&lt;th&gt;CLS相容&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;sbyte&lt;/td&gt;
					&lt;td&gt;System.Sbyte&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;byte&lt;/td&gt;
					&lt;td&gt;System.Byte&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;short&lt;/td&gt;
					&lt;td&gt;System.Int16&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ushort&lt;/td&gt;
					&lt;td&gt;System.UInt16&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;int&lt;/td&gt;
					&lt;td&gt;System.Int32&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;uint&lt;/td&gt;
					&lt;td&gt;System.Uint32&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;long&lt;/td&gt;
					&lt;td&gt;System.Int64&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ulong&lt;/td&gt;
					&lt;td&gt;System.Uint64&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;char&lt;/td&gt;
					&lt;td&gt;System.Char&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;float&lt;/td&gt;
					&lt;td&gt;System.Single&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;double&lt;/td&gt;
					&lt;td&gt;System.Double&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;bool&lt;/td&gt;
					&lt;td&gt;System.Boolean&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;decimal&lt;/td&gt;
					&lt;td&gt;System.Decimal&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;object&lt;/td&gt;
					&lt;td&gt;System.Object&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;System.String&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我们平时在写程序时通常都是使用基元类型，因为方便，但本书的作者认为应该直接使用FCL中的类型，原因如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在c#中long对应的FCL类型为System.Int64，但是在其他的语言中，如c++ 就将long视为一个Int32。这样习惯于一种编程语言的人在看另一种编程语言写的源码是就会产生错误的理解。&lt;/li&gt;
&lt;li&gt;在FCL中的许多的方法将类型名作为方法名的一部分，如System.Convert类提供ToBoolean,ToInt32,ToSingle等。这样在使用基元类型做类型转换时就感觉有点怪怪的，如：float val=Convert.ToSingle(“23”);&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="值类型和引用类型的区别"&gt;值类型和引用类型的区别&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;所有的值类型都是从System.TypeValue派生，如Struct Enum都是值类型；所有引用类型都是从System.Object派生。&lt;/li&gt;
&lt;li&gt;值类型分配在线程堆栈上，引用类型分配在托管堆上。&lt;/li&gt;
&lt;li&gt;值类型表现形式有未装箱形式和已装箱形式，而引用类型总是已装箱形式。&lt;/li&gt;
&lt;li&gt;所有的值类型都是sealed类型，所以值类型不能作为任何类型的基类型，也不能在值类型中引入虚方法。&lt;/li&gt;
&lt;li&gt;创建一个引用类型变量时，会被初始化为null，试图使用一个null的引用类型变量时，会抛出NullReferenceException异常，也就是常见的“未将对象引用设置到对象的实例”；值类型在创建时所有成员都初始化为0了，所以不会抛出该异常。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="原文例子表示值类型和引用类型的区别"&gt;原文例子表示值类型和引用类型的区别&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class Program
{
 static void Main(string[] args)
 {
 SomeRef r1 = new SomeRef();
 SomeVal v1 = new SomeVal();
 r1.x = 5;
 v1.x = 5;
 Console.WriteLine(r1.x); //5
 Console.WriteLine(v1.x); //5
 SomeRef r2 = r1;
 SomeVal v2 = v1;
 r1.x = 8;
 v1.x = 9;
 Console.WriteLine(r1.x); //8
 Console.WriteLine(r2.x); //9
 Console.WriteLine(v1.x); //9
 Console.WriteLine(v2.x); //5
 }
}
class SomeRef
{
 public Int32 x;
}
struct SomeVal
{
 public Int32 x;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="clr中类型字段布局的控制"&gt;CLR中类型字段布局的控制&lt;/h2&gt;
&lt;p&gt;为了提高性能，clr能按照所选择的任何方式来排列类型的字段。我们可以通过在类会是结构上使用System.Runtime.InteropServices.StructLayoutAttribute属性来改变这种排列的顺序。该属性接受一个LayoutKind的枚举值（Auto，Sequential，Explicit），默认情况下C#编译器会为类选择Atuo，为结构选择Sequential。下面来定义一个类和一个结构&lt;/p&gt;</description></item></channel></rss>