<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DotNet on 冯威的博客</title><link>https://fwhyy.com/tags/dotnet/</link><description>Recent content in DotNet on 冯威的博客</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Mon, 16 Dec 2024 16:23:00 +0800</lastBuildDate><atom:link href="https://fwhyy.com/tags/dotnet/atom.xml" rel="self" type="application/rss+xml"/><item><title>信创浪潮下的.NET困境与技术转型思考</title><link>https://fwhyy.com/2024/12/under-the-wave-of-innovation-and-entrepreneurship-net-dilemma-and-technological-transformation-thinking/</link><pubDate>Mon, 16 Dec 2024 16:23:00 +0800</pubDate><guid>https://fwhyy.com/2024/12/under-the-wave-of-innovation-and-entrepreneurship-net-dilemma-and-technological-transformation-thinking/</guid><description>&lt;p&gt;开始之前我想先介绍下什么是.NET、什么是信创？&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="什么是-net"&gt;什么是 .NET？&lt;/h2&gt;
&lt;p&gt;我们现在说 .NET 通常指 .NET Core 之后的版本。.NET Core 是跨平台的开源框架，不仅可以运行在 Windows，还支持 Linux 和 macOS。在 .NET Core 3.1 之后发布的 .NET 5 又做了大统一，名称中也去掉 Core 了），目前最新的版本为 .NET9 。&lt;/p&gt;
&lt;p&gt;.NET 有以下几个特点：&lt;/p&gt;
&lt;p&gt;1、采用最开放的 MIT/Apache 2 协议开源，具备中立性。&lt;/p&gt;
&lt;p&gt;2、归属中立的第三方组织 .NET 基金会管理，不属于任何商业公司，进一步增强了其独立性和开放性。&lt;/p&gt;
&lt;p&gt;3、完全支持 ARM 32/64 架构，适配国内主流的 ARM 架构芯片，如鲲鹏、飞腾等。&lt;/p&gt;
&lt;h2 id="什么是信创-"&gt;什么是信创 ？&lt;/h2&gt;
&lt;p&gt;信创，即信息技术应用创新产业，其核心目标是实现信息技术领域的自主可控，以保障国家信息安全。国资委 2022 年 79 号文件主要指示如下：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心内容&lt;/strong&gt;：要求在 5 年内国企全部完成信创替换。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;实施步骤&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;1、2022 年 11 月底，完成信创改造方案规划并报送国资委；&lt;/p&gt;
&lt;p&gt;2、2023 年 1 月起，每季度报送信息化系统信创改造的最新进度；&lt;/p&gt;
&lt;p&gt;3、2027 年底，全部央国企必须完成信息化系统的信创改造工作。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;替换要求&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;1、全面替换：OA、门户、邮箱、纪检、党群、档案、经营管理。&lt;/p&gt;
&lt;p&gt;2、应替就替：战略决策、ERP、风控管理、CRM 管理系统。&lt;/p&gt;
&lt;p&gt;3、能替就替：生产制造、研发系统。&lt;/p&gt;
&lt;p&gt;为什么要发展信创？&lt;/p&gt;
&lt;p&gt;1、&lt;strong&gt;保障国家信息安全&lt;/strong&gt;：随着信息技术的快速发展，网络安全风险日益增加，发展信创有助于提升国家信息安全水平。&lt;/p&gt;
&lt;p&gt;2、&lt;strong&gt;实现自主可控&lt;/strong&gt;：历史上，中国在信息技术领域长期依赖国外技术，发展信创可以推动国内信息技术产业的发展，减少对外部技术的依赖。&lt;/p&gt;
&lt;p&gt;4、&lt;strong&gt;应对国际竞争&lt;/strong&gt;：在全球信息技术产业竞争加剧的背景下，发展信创产业有助于提升国家的国际竞争力。&lt;/p&gt;
&lt;p&gt;4、&lt;strong&gt;促进数字化转型&lt;/strong&gt;：信创产业的发展有利于国内企业更安全地完成数字化转型。&lt;/p&gt;
&lt;h2 id="net-支持信创吗"&gt;.NET 支持信创吗？&lt;/h2&gt;
&lt;p&gt;毫无疑问，从技术上来说，.NET 是支持信创的。&lt;/p&gt;
&lt;p&gt;但是，这没有用，客户不听解释。&lt;/p&gt;
&lt;p&gt;随着 27 年的临近，企业的信创进程在加快。最近见了不少客户，不管是否了解技术，都谈 .NET 色变，有的更是将 .NET 纳入了黑名单。有客户原话是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我也知道 .NET 是支持信创的，但集团下了文，不让用，我们也没有办法。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;幸好我们产品比较开放，很早就是多技术栈并行的。不过也很无奈，需要全面进行技术栈迁移了。&lt;/p&gt;
&lt;h2 id="转型"&gt;转型&lt;/h2&gt;
&lt;p&gt;说到无奈，是因为要做出改变，就要离开舒适区了。但仔细想想，舒适区待久了很难让人进步。这次的转型也许会成为再上一层楼的一个契机。转型分为两个层面：技术和业务。&lt;/p&gt;
&lt;h3 id="技术"&gt;技术&lt;/h3&gt;
&lt;p&gt;1、代码块节点使用到的 nodejs、python 还是继续保留。&lt;/p&gt;
&lt;p&gt;2、剩余的 .NET 部分全部转换为 Java。&lt;/p&gt;
&lt;p&gt;3、转换后的 Java 程序需要和原来的 Java 代码一起通盘考虑，架构上需要重新考虑和规划。&lt;/p&gt;
&lt;p&gt;4、合理梳理业务链路、优化缓存的使用，进一步提升性能、稳定性和扩展性。&lt;/p&gt;
&lt;h3 id="业务"&gt;业务&lt;/h3&gt;
&lt;p&gt;我们的产品为低代码类型的产品，目的是能快速高效地为客户落地业务。现在随着 AI 技术的发展，我们产品也需要做出相应的变化。&lt;/p&gt;</description></item><item><title>.NET中操作哨兵模式的Redis（哨兵和Redis示例配置密码）</title><link>https://fwhyy.com/2023/12/redis-for-operating-sentinel-mode-in-net/</link><pubDate>Mon, 25 Dec 2023 17:03:06 +0800</pubDate><guid>https://fwhyy.com/2023/12/redis-for-operating-sentinel-mode-in-net/</guid><description>&lt;p&gt;Redis 的高可用有一种方式是部署成哨兵模式。在哨兵模式中哨兵和每个节点都可以设置密码，如果都设置密码了，在 .NET 中用 CSRedisCore 进行调用时会遇到点问题。&lt;/p&gt;
&lt;p&gt;本文就介绍怎样用 CSRedisCore 来调用设置了密码的哨兵模式 Redis。&lt;/p&gt;</description></item><item><title>NET Core3.1 升级到 NET8</title><link>https://fwhyy.com/2023/12/dotnet-3-upgrade-to-dotnet-8/</link><pubDate>Fri, 08 Dec 2023 17:00:06 +0800</pubDate><guid>https://fwhyy.com/2023/12/dotnet-3-upgrade-to-dotnet-8/</guid><description>&lt;p&gt;.NET Core 3.1 已经用了很长一段时间，其实在 2022 年的年底微软已经不提供支持了，后面的一个 LTS 版本 .NET 6 也会在 2024 年 11 月终止支持，所以直接升级到 .NET 8 是最好的选择。&lt;/p&gt;</description></item><item><title>.NET8 正式发布， C#12 新变化</title><link>https://fwhyy.com/2023/11/dotnet-8/</link><pubDate>Fri, 17 Nov 2023 16:38:50 +0800</pubDate><guid>https://fwhyy.com/2023/11/dotnet-8/</guid><description>&lt;p&gt;在 .NET Conf 2023 大会上，.NET 8 正式发布了，.NET 8 是一个长期支持（LTS）版本，这意味着可以获得三年的支持和补丁。我们也计划将框架从 .NET Core3.1 升级到 8 ，关于如何升级等升级完成后再来分享。&lt;/p&gt;</description></item><item><title>dotNET 升级利器：Upgrade Assistant</title><link>https://fwhyy.com/2023/03/dotnet-upgrade-assistant/</link><pubDate>Mon, 20 Mar 2023 11:29:39 +0800</pubDate><guid>https://fwhyy.com/2023/03/dotnet-upgrade-assistant/</guid><description>&lt;p&gt;.NET 发展很快, 现在 .NET 8 的预览版已经发布了，但我们现在还在使用 .NET Core 3.1，将 .NET 升级到 .NET 6 已经势在必行。&lt;/p&gt;</description></item><item><title>dotNET 7：最小 API 使用</title><link>https://fwhyy.com/2022/11/dotmet-7-minimal-api-usage/</link><pubDate>Mon, 21 Nov 2022 08:39:37 +0800</pubDate><guid>https://fwhyy.com/2022/11/dotmet-7-minimal-api-usage/</guid><description>&lt;p&gt;Minimal APIs 并不是在 .NET 7 中才加入的，记得应该是在 .NET 6 中就已经提供，只是对我来说，到现在才开始使用。&lt;/p&gt;</description></item><item><title>dotNET 7 尝鲜（VS 和 C# 11)</title><link>https://fwhyy.com/2022/11/dotnet-7-early-edition/</link><pubDate>Thu, 10 Nov 2022 18:39:37 +0800</pubDate><guid>https://fwhyy.com/2022/11/dotnet-7-early-edition/</guid><description>&lt;p&gt;2022 年 11 月 8 日，.NET 7 正式发布了，从 11 月 8 号 到 10 号，线上的 .NET Conf 2022 会议正在举行，可以通过 &lt;a href="https://www.dotnetconf.net/"&gt;https://www.dotnetconf.net/&lt;/a&gt; 了解相关情况。&lt;/p&gt;</description></item><item><title>dotNet 5 中执行 Node.js</title><link>https://fwhyy.com/2021/08/dotnet5-exec-node-js/</link><pubDate>Mon, 09 Aug 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/08/dotnet5-exec-node-js/</guid><description>&lt;p&gt;在&lt;a href="http://mp.weixin.qq.com/s?__biz=MzU0NjgzNzQyMw==&amp;amp;mid=2247484621&amp;amp;idx=1&amp;amp;sn=e23179a553c2cf80f5b2d0d351c75065&amp;amp;chksm=fb56c20dcc214b1b17894f1afb6070024cd1321811182d202437cea4baaecf34e69f27ad0978&amp;amp;scene=21#wechat_redirect"&gt;低代码产品&lt;/a&gt;中为了扩展功能，我们在业务编排中会扩展代码块的功能，允许用户直接在界面中进行代码（Node.js、 Python）的编写，来实现取数或者赋值的一些功能。本文简单介绍下在 dotNET 5 中怎么样进行 Node.js 的调用以及怎样部署到 CentOS 和 Docker 容器中。&lt;/p&gt;
&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;dotNET ：5&lt;/li&gt;
&lt;li&gt;Node.js：14.17.4&lt;/li&gt;
&lt;li&gt;CentOS：7.6&lt;/li&gt;
&lt;li&gt;Docker：19.03.13&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dotnet-5-中的代码实现"&gt;dotNET 5 中的代码实现&lt;/h2&gt;
&lt;p&gt;1、在 VS 中创建 WebAPI 示例项目 nodejs-demo 项目，目标框架选择 .NET 5.0。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/20220202081223.webp" alt="iShot2022-02-02 08.12.23" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2、在项目中引入 NuGet 包：Microsoft.AspNetCore.NodeServices ,这里我使用的是 5.0 的预览版本。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202202020813752.webp" alt="iShot2022-02-02 08.13.07" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3、修改 Startup 类，在 ConfigureServices 方法中添加下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;services.AddNodeServices();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4、在项目的根目录中创建一个名为 hello.js 的脚本文件，文件的属性中的「复制到输出目录」设置为「始终复制」，文件的内容如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;module.exports = function (callback, name) {
 var msg = &amp;#39;Hello,&amp;#39; + name;
 callback(null, msg);
};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5、编写一个 API 接口方法：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[HttpGet]
public async Task&amp;lt;IActionResult&amp;gt; Get([FromServices] INodeServices nodeServices)
{
 var result = await nodeServices.InvokeAsync&amp;lt;string&amp;gt;(&amp;#34;hello.js&amp;#34;, &amp;#34;oec2003&amp;#34;);
 return Ok(result);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;6、如果正常运行，结果如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202202020813556.webp" alt="iShot2022-02-02 08.13.29" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="部署到-centos-中"&gt;部署到 CentOS 中&lt;/h2&gt;
&lt;p&gt;1、在 Node.js 的中文官网 (&lt;a href="http://nodejs.cn/download/current/"&gt;http://nodejs.cn/download/current/&lt;/a&gt;) 下载 Linux 二进制文件 (x64) 的安装包；&lt;/p&gt;
&lt;p&gt;2、将下载的安装包 node-v14.17.4-linux-x64.tar.xz 复制到 CentOS 系统的 root 目录中；&lt;/p&gt;
&lt;p&gt;3、执行命令 &lt;code&gt;tar -xvf node-v14.17.4-linux-x64.tar.xz&lt;/code&gt; 解压安装文件；&lt;/p&gt;
&lt;p&gt;4、执行命令 &lt;code&gt;mv node-v14.17.4-linux-x64 nodejs&lt;/code&gt; 将解压后的文件夹命名为 nodejs；&lt;/p&gt;</description></item><item><title>Remoting 外网访问</title><link>https://fwhyy.com/2016/09/remoting-external-access/</link><pubDate>Tue, 06 Sep 2016 22:01:52 +0800</pubDate><guid>https://fwhyy.com/2016/09/remoting-external-access/</guid><description>&lt;p&gt;Remoting 是一种很古老的分布式技术，如果不清楚的可以参考下面三篇博客，写的非常详细：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html"&gt;Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html"&gt;Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/wayfarer/articles/75213.html"&gt;Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最近解决公司一个老平台的问题，该平台中使用了 Remoting 技术，现有的环境大致如下：&lt;/p&gt;
&lt;p&gt;1、Remoting 服务和 Web 都是部署在局域网；
2、多台 Web 都是通过内网 IP 和端口来访问 Remoting 。&lt;/p&gt;</description></item><item><title>开源上传组件stream的.Net后台实现</title><link>https://fwhyy.com/2015/08/stream-aspnet/</link><pubDate>Thu, 13 Aug 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/08/stream-aspnet/</guid><description>&lt;p&gt;stream是一款功能很强大的上传组件，支持Html5和Flash两种方式，Html5可以支持断点续传，进度、剩余时间等的显示。但后台代码实现目前只有Java和PHP的版本，参考PHP的版本我实现了一个.Net的版本，目前只支持Html5的方式，代码已经放到了Github上：&lt;/p&gt;</description></item><item><title>VS2010和VS2008使用不同编译方式在64位机器生成注册表对比</title><link>https://fwhyy.com/2012/10/gen-reg-in-vs2010-and-vs2008/</link><pubDate>Sun, 14 Oct 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/10/gen-reg-in-vs2010-and-vs2008/</guid><description>&lt;p&gt;最近写一个小工具用到了使用C#来进行注册表的操作，使用C#来进行注册表的操作需要引入命名空间Microsoft.Win32，关于操作注册表的帮助类可以参考RegHelper.cs。下面分别使用VS2010和VS2008使用Any CPU、X64、X86和Itanium进行编译，运行在32位机器和64位机器进行对比。看下面一段代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;string subkey = @&amp;#34;software\FW\UserInfo&amp;#34;;
RegHelper reg = new RegHelper(subkey, RegDomain.LocalMachine);
reg.CreateSubKey(subkey);
Console.ReadLine();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面代码的本意是在注册表中创建&lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\FW\UserInfo&lt;/code&gt; 节点，在32位机器中没有什么问题，可以正常的生产节点，但在64位机器上，不同的VS版本，使用不同的编译模式，会产生不一样的结果。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300649603.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>C# &amp; .NET 1.0-4.0</title><link>https://fwhyy.com/2012/09/c-net-1-0-4-0/</link><pubDate>Sun, 02 Sep 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/09/c-net-1-0-4-0/</guid><description>&lt;p&gt;学习和使用.NET平台已有六七个年头了，05年开始学习.NET的时候，当时网上的资源不像现在这样丰富，所以去电脑城买了张盗版的VS2005的光盘，安装时才发现是VS2003，当时有一种被坑的感觉，但也正是如此，让我有了一个完整的.NET的学习生涯。&lt;/p&gt;
&lt;p&gt;从我从业的经历来看VS2003和VS2008是使用的比较多的，一些历史遗留的老项目由种种原因没有升级，依然在使用VS2003。我现在所在的公司也只使用VS2003和VS2008这两种开发工具，尽管TFS已经是2010了。很多时候公司觉得够用也就不去升级开发工具了。从1.0到4.0的变化主要体现在DotNet平台、语言和开发工具这三个方面。本文只是概括性的讲述在每个版本里都有些什么新的特性。先看下面的一张表格，描述的不同版本的出生年份、对应的VS版本和CLR的版本。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290756052.webp" alt="2012-07-04_230408" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中需要注意的一点是：2.0 3.0 3.5的CLR版本都是2.0。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;在1.1版本中，从语言的角度就是基本的面向对象的语法，可以说任何一般C#语言的书籍都包含了C#1的所有内容。工具方面VS2003已经很强大了，即便是到了现在的VS2012，我们80%时候用到的也只不过是20%的功能。&lt;/p&gt;
&lt;p&gt;在VS2003中创建ASP.NET项目默认是跟IIS相关联的，从VSS中拉VS2003的代码时需要先在IIS中创建好站点，端口要和VSS中代码的相对应，但有时会出现很多问题。我一般的做法是将代码拉到本地后，修改解决方案文件中的路径为本地路径，然后修改项目文件中的ProjectType为Local，默认是Web，就可以很顺利打开项目了。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;2.0中对应VS2005我用的也不多，因为很快就被VS2008替代了，不过在语言方面却带来了很多新的东西。&lt;/p&gt;
&lt;p&gt;★C#2中最重要的一个特性应该就是泛型。泛型的用处就是在一些场景下可以减少强制转换来提高性能。在C#1中就有很多的强制转换，特别是对一些集合进行遍历时，如ArrayList、HashTable，因为他们是为不同数据类型设计的集合，所以他们中键和值的类型都是object，这就意味着会平凡发生装箱拆箱的才做。C#2中有了泛型，所以我们可以使用List&lt;T&gt;、Dictionary&amp;lt;Tkey,TValue&amp;gt; 。泛型能够带来很好的编译时类型检查，也不会有装箱拆箱的才做，因为类型是在使用泛型的时候就已经指定了。&lt;/p&gt;
&lt;p&gt;DotNet已经通过了很多的泛型类型供我们使用，如上面提到的List&lt;T&gt;,Dictionary&amp;lt;Tkey,TValue&amp;gt;,我们也可以自己来创建泛型类型(类、接口、委托、结构)或是方法。在定义泛型类型或时可以通过定义泛型约束来对泛型参数进行限制，更好的使用编译时检查。泛型约束是通过关键字where来实现的，C#2中的泛型约束有4种：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引用类型约束：确保类型实参是引用类型，使用where T:class来表示；&lt;/li&gt;
&lt;li&gt;值类型约束：确保类型实参是值类型，使用where T:truct来表示；&lt;/li&gt;
&lt;li&gt;构造函数类型约束，使用where T:new()来表示；&lt;/li&gt;
&lt;li&gt;转换类型约束：约束类型实参是另外的一种类型，例如：where T:IDisposable 。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;★C#2提供了分部类（Partil）。分部类可以允许我们在多个文件中为一个类型编写代码，在Asp.Net2.0中用的极为广泛。新建一个Aspx页面，页面的CodeBehind和页面中的控件的定义就是通过分部类来实现的。如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public partial class _Default : System.Web.UI.Page 
public partial class _Default 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;分布类使用关键字partial来定义，当一个类中的代码非常多时，可以使用分部类来进行拆分，这对代码的阅读很有好处，而且不会影响调用。&lt;/p&gt;
&lt;p&gt;★C#2中增加了静态类，静态类中的公用方法必须也是静态的，可以由类名直接调用，不需要实例化，比较适用于编写一些工具类。如System.Math类就是静态类。工具类有一些特点，如：所有成员都是静态的、不需要被继承、不需要进行实例化。在C#1中我们可以通过如下代码来实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//声明为密封类防止被继承 
public sealed class StringHelper
{
 //添加私有无参构造函ˉ数防止被实例化，如果不添加私有构造函数 //会自动生成共有无参构造函数 
 private StringHelper(){};
 public static int StringToInt32(string input)
 {
 int result=0;
 Int32.TryParse(input, out result);
 return result;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;C#2中可以使用静态类来实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public static class StringHelper
{
 public static int StringToInt32(string input)
 {
 int result=0;
 Int32.TryParse(input, out result);
 return result;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;★在C#1中声明属性，属性中的get和set的访问级别是和属性一致，要么都是public要么都是private，如果要实现get和set有不同的访问级别，则需要用一种变通的方式，自己写GetXXX和SetXXX方法。在C#2中可以单独设置get和set的访问级别，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private string name;
public string Name
{
 get { return name; }
 private set { name = value; }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;需要注意的是，不能讲属性设置为私有的，而将其中的get或是set设置成公有的，也不能给set和get设置相同的访问级别，当set和get的访问级别相同时，我们可以直接设置在属性上。&lt;/p&gt;
&lt;p&gt;★命名空间可以用来组织类，当不同的命名空间中有相同的类时，可以使用完全限定名来防止类名的冲突，C#1中可以使用空间别名来简化书写，空间别名用using关键字实现，看下面一个例子:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace NameSpaceDemo1
{
 public class ClassDemo{}
}
namespace NameSpaceDemo2
{
 public class ClassDemo{}
}
using Demo1 = NameSpaceDemo1;
using Demo2 = NameSpaceDemo2;
namespace WebApplication2
{
 public partial class _Default : System.Web.UI.Page 
 {
 protected void Page_Load(object sender, EventArgs e)
 {
 Demo1.ClassDemo c1 = new Demo1.ClassDemo();
 Demo2.ClassDemo c2 = new Demo2.ClassDemo();
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果我们在使用中添加了名为Demo1或是Demo2的类，那么空间别名的使用就会受到影响，在C#1中就得使用完全限定名了。在C#2中可以用“::”符号来解决，如下面代码：&lt;/p&gt;</description></item><item><title>使用MicroSoft CLR Debug来调试较大项目</title><link>https://fwhyy.com/2011/07/use-microsoft-clr-debug-to-debug-larger-projects/</link><pubDate>Wed, 20 Jul 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/07/use-microsoft-clr-debug-to-debug-larger-projects/</guid><description>&lt;p&gt;在以前的开发中，调试时很自然的会直接按F5进行调试，有时项目部署在IIS中也只是将项目的服务器指向IIS，仍然是将整个项目运行设置断点进行调试。最近遇到了一个问题，项目很大，直接F5运行会导致VS卡死，这种时候使用MicroSoft CLR Debug来进行调试是最合适不过了。&lt;/p&gt;
&lt;p&gt;首先打开MicroSoft CLR Debug&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710632.webp" alt="2011-07-18_164829" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;打开后界面如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710108.webp" alt="2011-07-18_164908" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;从项目中选择一个需要调试的文件，并在需要调试的地方设置断点&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710393.webp" alt="2011-07-18_165017" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“调试”-“附加到进程”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710454.webp" alt="2011-07-18_165041" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;附加进程前确保你的项目已经运行，如果是Win2003系统，会有一个w3wp.exe的进程存在,如果是xp系统，该进程名是aspnet_wp.exe。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710503.webp" alt="2011-07-18_165126" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;此时运行程序就会命中断点，个人认为此方法比较适用于将项目部署到IIS中进行调试，此方法的几个优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不会占用很多资源，只需要将需要调试的文件添加进来设置断点即可。&lt;/li&gt;
&lt;li&gt;如果是管理系统之类的项目，只需要登陆一次即可，不需要每次调试时都重新登陆。&lt;/li&gt;
&lt;li&gt;退出调试不会对运行的程序有什么影响，如果是F5进行调试，退出调试页面就关闭了。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>微软最新的 Web 开发工具WebMatrix的简单介绍及安装</title><link>https://fwhyy.com/2011/01/the-latest-microsoft-web-development-tools-webmatrix-simple-introduction-and-installation/</link><pubDate>Fri, 14 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/the-latest-microsoft-web-development-tools-webmatrix-simple-introduction-and-installation/</guid><description>&lt;p&gt;今天很给力，微软Asp.Net团队同时发布了WebMatrix,Razor,MVC3以及Orchard四个产品，其中&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;WebMatrix&lt;/a&gt; 是微软最新的 Web 开发工具，它包含了构建网站所需要的一切元素。您可以从开源 Web 项目或者内置的 Web 模板开始，也可以直接从无到有编写代码。简单并且完全是免费的。开发网站从来没有如此简单。&lt;/p&gt;
&lt;p&gt;什么介绍也没有官方的详细，我就将官网的介绍文字引用过来吧，当然你也可以访问&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;http://www.microsoft.com/web/webmatrix/&lt;/a&gt;进行了解。&lt;/p&gt;
&lt;h2 id="建立您的网站"&gt;建立您的网站&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;为了开始建立网站，您只需要使用 Microsoft Web 平台安装器下载并安装 WebMatrix。这只会占用您短短的5分钟时间。当 WebMatrix 成功安装后，您可以非常方便地获得并下载最新版本的免费 Web 应用，如 WordPress, Joomla!, DotNetNuke 和 Orchard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="自定义您的网站"&gt;自定义您的网站&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;您会发现 WebMatrix 在一个统一界面中提供了您需要的一切工具的特性，不需要再花费精力于在多种应用工具切换来完成一般性的 Web 开发任务。通过 WebMatrix，您只需要一步点击，即可编辑文件，管理数据库和更改服务器设置等。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="发布您的网站"&gt;发布您的网站&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;当您完成网站开发后，WebMatrix 提供了最快速的方法来发布。通过访问托管服务库，您可以找到提供托管服务的合作伙伴，并且您可以直接通过 WebMatrix 来发布您的网站。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;WebMatrix&lt;/a&gt;的安装需要连接到网络，进入到官方网站，下载下exe的安装文件，双击进入安装。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105019.webp" alt="2011-01-14_125505" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201302105421.webp" alt="2011-01-14_125530" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201302105543.webp" alt="2011-01-14_125600" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“安装”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105185.webp" alt="2011-01-14_125634" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“我接受”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105768.webp" alt="2011-01-14_125655" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;等待下载完成，自动进行安装&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105713.webp" alt="2011-01-14_130224" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;再稍等几分钟&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105235.webp" alt="2011-01-14_131824" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“完成”，就安装完成了，Web平台安装程序3.0 的界面如下，我们可以自行添加需要的项目进行安装&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105836.webp" alt="2011-01-14_133049" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;刚刚接触&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;WebMatrix&lt;/a&gt;，会尽快抽时间好好体验一下，然后写成博文与大家分享。&lt;/p&gt;</description></item><item><title>Visual Studio 2010 Beta 2 公开下载地址</title><link>https://fwhyy.com/2009/10/visual-studio-2010-beta-2-download-address-publicly/</link><pubDate>Thu, 22 Oct 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/10/visual-studio-2010-beta-2-download-address-publicly/</guid><description>&lt;p&gt;前天就在博客园见了lyj的那篇介绍Visual Studio 2010 Beta 2的文章了，今天终于开发下载了。
下载地址：&lt;a href="http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx"&gt;http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;看了下别人的安装截图感觉漂亮了不少，不过我还是想等到正式版出来后再下载安装，希望到时能换一个配置好点的本本，现在的这个已经陪伴我三四年的老本跑起来确实很吃力啊。&lt;/p&gt;
&lt;h2 id="相关文章"&gt;相关文章&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/10/experience-vs2010-improvements/"&gt;体验vs2010 （功能改进篇）&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/10/experience-vs2010-installation/"&gt;体验VS2010（安装篇）&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/05/net-4-vs2010-new-features/"&gt;Net4.0—VS2010新特性&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/07/net-4-data-bound-controls-the-clientidrowsuffix-properties/"&gt;Net4.0—数据绑定控件（GridView ListView…）中的ClientIDRowSuffix属性&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/07/net-4-purification-processing-of-html/"&gt;Net4.0—对HTML净化的处理&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/07/net-4-aspnet-controls-the-hyperlink-in-the-improvement/"&gt;Net4.0—AspNet中的控件HyperLink的改进（支持路由跳转）&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/07/net-4-aspnet-url-rewriting-in-the-improvement/"&gt;Net4.0—AspNet中URL重写的改进&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/06/net-4-the-web-deployment-tool/"&gt;Net4.0—Web部署工具&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/05/net-4-framwork-of-new-features/"&gt;Net4.0—Framwork新增特性&lt;/a&gt;&lt;/p&gt;</description></item><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# 学习笔记（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><item><title>在vs2008中设置jquery智能提示</title><link>https://fwhyy.com/2009/05/in-setting-the-jquery-vs2008-intellisense/</link><pubDate>Wed, 20 May 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/05/in-setting-the-jquery-vs2008-intellisense/</guid><description>&lt;p&gt;1 要确保您的vs2008已经打了sp1补丁，可以点击&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=27673C47-B3B5-4C67-BD99-84E525B5CE61&amp;amp;displaylang=zh-cn"&gt;这里&lt;/a&gt;下载&lt;/p&gt;
&lt;p&gt;2 下载 jQuery-vsdoc.js ，如果您安装了asp.net mvc ，可以在mvc的项目下的srcipts目下找到，或是点击&lt;a href="http://docs.jquery.com/Downloading_jQuery#Download_jQuery"&gt;这里&lt;/a&gt;下载。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300705034.webp" alt="2010-12-30_104425" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 下载安装一个vs2008支持 -vsdoc.js 智能提示的一个补丁 ，可以点击这里下载&lt;/p&gt;
&lt;p&gt;4 准备工作已经做完，现在就可以来试试jquery的智能提示了，用vs2008新建一个项目，在页面的head标签里添加对jquery-1.3.2-vsdoc.js的引用&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300705137.webp" alt="2010-12-30_104506" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5 现在在js的方法中敲一个$符号，智能提示就会弹出来。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300705914.webp" alt="2010-12-30_104541" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;参考文章：&lt;a href="http://weblogs.asp.net/scottgu/archive/2008/11/21/jquery-intellisense-in-vs-2008.aspx"&gt;http://weblogs.asp.net/scottgu/archive/2008/11/21/jquery-intellisense-in-vs-2008.aspx&lt;/a&gt;&lt;/p&gt;</description></item><item><title>DotNet 3.0 框架介绍</title><link>https://fwhyy.com/2007/08/dotnet-3-0-framework-introduce/</link><pubDate>Fri, 10 Aug 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/08/dotnet-3-0-framework-introduce/</guid><description>&lt;p&gt;微软.NET的最新版本，.NET Framework 3.0，为开发下一代业务解决方案软件系统开启了新的可能。它的设计目标是：提高生产力，降低基础设施复杂性，提供一个一致的元系统，让企业级服务、工作流解决方案和用户体验软件系统的开发更容易。&lt;/p&gt;</description></item><item><title>.Net泛型编程简介</title><link>https://fwhyy.com/2007/05/net-generic-programming/</link><pubDate>Tue, 22 May 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/05/net-generic-programming/</guid><description>&lt;p&gt;.NET泛型编程已经离我们不远了，在微软最近随SQL Server Yukon Beta1发行的.NET Framework 1.2中就已经有了泛型的影子。虽然现在它还是问题多多，但是相信随着新版.NET Framework的正式发行（正式发行时的版本号会是2.0），这些问题会得到解决。因此我们也该为.NET泛型编程做些准备了。&lt;/p&gt;</description></item></channel></rss>