- .NET 指南
- 开始操作
- .NET 教程
- .NET 体系结构组件
- .NET Standard
- 什么是.NET 标准中的新增功能
- 目标框架
- .NET 术语表
- 使用 mdoc 生成文档
- .NET 的体系结构指南
- 使用 ASP.NET Core 和 Azure 构建新式 Web 应用程序
- 现代 Web 应用程序的特征
- 传统 Web 应用程序和单页面应用程序 (Spa) 之间进行选择
- 常见的客户端 Web 技术
- 开发 ASP.NET Core MVC 应用程序
- 使用 ASP.NET Core 应用中的数据
- 测试 ASP.NET Core MVC 应用程序
- Azure 的开发过程
- Azure 托管的 ASP.NET 核心 Web 应用的建议
- 使用 Azure 云和 Windows 容器更新现有 .NET 应用程序 (v1.0)
- 提升和移动现有应用 Azure IaaS
- 将关系数据库迁移到 azure
- 直接迁移现有应用 DevOps
- 到提起并移动现有的.NET 应用到云 DevOps 通用应用程序的原因
- 云 devops 通用应用程序中的 Microsoft 技术
- 云优化应用程序如何呢?
- 如何将现有的.NET 应用程序部署到 Azure App Service
- 将现有的.NET 应用程序部署为 Windows 容器
- 何时不将部署到 Windows 容器
- 何时在你的本地部署 Windows 容器 IaaS VM 基础结构
- 何时将 Windows 容器部署到 Azure Vm (IaaS 云)
- 何时到 Service Fabric 中部署 Windows 容器
- 何时将 Windows 容器部署到 Azure 容器服务 (即,Kubernetes)
- 构建可复原的服务供云: 采用在云中的暂时性故障
- 更新你的应用的监视和遥测
- 更新使用 CI/CD 管道和 DevOps 工具在云中的应用程序的生命周期
- 将迁移到混合云方案
- 演练和技术获取启动的概述
- 技术演练列表
- 技术演练列表
- 结论
- 容器和 Docker 简介
- 什么是 Docker?
- Docker 术语
- Docker 容器、 图像和注册表
- Docker 应用程序生命周期的介绍
- DevOps 协作基础的容器
- 有关适用于容器化应用的 Microsoft 平台和工具的简介
- 使用 Docker 和 Microsoft Azure 设计和开发容器化应用
- Docker 应用程序设计
- 常见容器设计原则
- 整体应用程序
- 状态和 Docker 应用程序中的数据
- SOA 应用程序
- 协调微服务和以高可伸缩性和可用性的 multicontainer 应用程序
- Docker 应用的开发环境
- 对于 Docker 应用程序的内部循环开发工作流
- 使用 Visual Studio Tools for Docker (在 Windows 上的 Visual Studio)
- 使用在 DockerFile 中的 Windows PowerShell 命令来设置 Windows 容器 (Docker 标准基于)
- 使用 Microsoft 工具的 Docker 应用程序 DevOps 工作流
- Docker 应用程序的外部循环 DevOps 工作流中的步骤
- 运行、管理和监视 Docker 生产环境
- 在生产环境中运行由和基于微服务的应用程序
- 管理生产 Docker 环境
- 监视容器化应用程序服务
- 关键结论
- .NET 微服务。 适用于容器化 .NET 应用程序的体系结构
- .NET 微服务。 适用于容器化 .NET 应用程序的体系结构
- 容器和 Docker 简介
- 什么是 Docker?
- Docker 术语
- Docker 容器、 图像和注册表
- 为 Docker 容器选择 .NET Core 还是 .NET Framework
- 一般性指导原则
- 何时选择 Docker 容器中的.NET 核心
- 何时选择 Docker 容器中的.NET Framework
- 决策表:.NET 框架,用于 Docker
- .NET 容器定向到何种操作系统
- 正式.NET Docker 映像
- 构建基于容器和微服务的应用程序
- Containerizing 整体应用程序
- 状态和 Docker 应用程序中的数据
- 面向服务的体系结构
- 微服务体系结构
- 每个微服务构成的数据自主性
- 与物理体系结构的逻辑体系结构
- 分布式的数据管理挑战和解决方案
- 标识每个微服务的域模型边界
- 直接与 API 网关模式的微服务构成客户端通信
- 在微服务体系结构的通信
- 基于消息的异步通信
- 创建、 不断发展,和版本控制 microservice Api 和协定
- 微服务可寻址性和服务注册表
- 创建复合 UI 基于微服务,包括 visual UI 形状和布局由多个微服务生成
- 复原和微服务中的高可用性
- 协调微服务和多容器应用程序的高可伸缩性和可用性
- 使用 Azure Service Fabric
- 基于 Docker 的应用程序的开发流程
- Docker 应用的开发工作流
- 在 Linux 或 Windows Nano Server 主机上部署基于单容器的 .NET Core Web 应用
- 将旧版整体式 .NET Framework 应用程序迁移到 Windows 容器
- 设计和开发基于微服务的多容器 .NET 应用程序
- 设计面向微服务构成的应用程序
- 创建简单的数据驱动 CRUD 微服务
- 定义与 docker-compose.yml 多容器应用程序
- 使用运行的容器的数据库服务器
- 实现基于事件的微服务 (集成事件) 之间的通信
- 实现使用 RabbitMQ 开发或测试环境事件总线
- 订阅事件
- 测试 ASP.NET 核心服务和 web 应用
- 使用 DDD 和 CQRS 模式降低微服务中的业务复杂性
- 应用中的微服务构成的简化的 CQRS 和 DDD 模式
- EShopOnContainers DDD 微服务中的应用 CQRS 和 CQS 方法
- 在 CQRS 微服务中实现读取/查询
- 设计 DDD 面向微服务
- 设计 microservice 域模型
- 实现 microservice 域模型与.NET 核心
- Seedwork (可重用基类,这些类和接口,您的域模型)
- 实现值对象
- 使用枚举类,而不枚举类型
- 设计域模型层中的验证
- 客户端验证 (验证在表示层)
- 域事件: 设计和实现
- 设计基础结构持久性层
- 实现与实体框架核心基础结构持久性层
- 作为持久性基础结构使用 NoSQL 数据库
- 设计微服务应用程序层和 Web API
- 实现微服务应用程序层使用 Web API
- 实现具有恢复能力的应用程序
- 处理部分失败
- 用于处理部分失败的策略
- 实现重试使用指数退让
- 实现弹性 Entity Framework 核心 SQL 连接
- 实现自定义 HTTP 调用的重试使用指数退让
- 使用 Polly 和实施 HTTP 调用重试使用指数退让
- 实现断路器模式
- 运行状况监视
- 保护 .NET 微服务和 Web 应用程序
- 有关在.NET 微服务和 web 应用程序的授权
- 在开发过程中安全地存储应用程序机密
- 使用 Azure 密钥保管库在生产时保护机密
- 记住的要点
- 为服务器应用选择 .NET Core 或 .NET Framework
- 什么是 托管代码 ?
- Automatic Memory Management
- 公共语言运行时 (CLR)
- 语言独立性和与语言无关的组件
- 语言独立性和与语言无关的组件
- 框架库
- .NET Framework 类库概述
- 在 .NET 中使用基类型
- 常规类型系统
- .NET Framework 中的类型转换
- .NET 中的类型转换表
- .NET 中的格式化类型
- 标准数字格式字符串
- 自定义数字格式字符串
- 标准日期和时间格式字符串
- 自定义日期和时间格式字符串
- 标准 TimeSpan 格式字符串
- 自定义的 TimeSpan 格式字符串
- 枚举格式字符串
- 复合格式设置
- 执行格式设置操作
- 如何:用前导零填充数字
- 如何:从特定日期中提取星期几
- 如何:定义和使用自定义数值格式提供程序
- 如何:往返日期和时间值
- 如何:将用户在 Web 控件中输入的数值转换为数字
- 如何:向 Web 用户显示本地化的日期和时间信息
- 如何:显示日期和时间值中的毫秒
- 如何:用非公历日历显示日期
- 操作在.NET 中的字符串
- 在.NET 中使用字符串的最佳做法
- .NET 中的基本字符串操作
- 在.NET 中创建新的字符串
- 剪裁和移除从.NET 中的字符串的字符
- .NET 中的空白字符串
- 比较.NET 中的字符串
- 更改.NET 中的大小写
- 在.NET 中使用 StringBuilder 类
- 如何: 在.NET 中执行基本字符串操作
- .NET 正则表达式
- 正则表达式语言 - 快速参考
- 正则表达式中的字符转义
- 正则表达式中的字符类
- 正则表达式中的定位点
- 正则表达式中的分组构造
- 正则表达式中的限定符
- 正则表达式中的反向引用构造
- 正则表达式中的备用构造
- 正则表达式中的替代
- 正则表达式选项
- 正则表达式中的其他构造
- .NET 中的正则表达式的最佳实践
- 正则表达式对象模型
- 正则表达式行为的详细信息
- 正则表达式中的回溯
- 正则表达式中的编译和重复使用
- 正则表达式中的线程安全
- 正则表达式示例
- 正则表达式示例:扫描 HREF
- 正则表达式示例:更改日期格式
- 如何:从 URL 中提取协议和端口号
- 如何:从字符串中剥离无效字符
- 如何:确认字符串是有效的电子邮件格式
- 在.NET 中编码的字符
- 在.NET 中分析字符串
- NET 中分析数值字符串
- 分析日期和时间字符串.NET 中
- .NET 中分析其他字符串
- .NET 类库
- .NET 可移植性分析器
- 在 .NET 中处理和引发异常
- .NET 程序集文件格式
- 内存管理和.NET 中的垃圾回收
- 垃圾回收
- 垃圾回收的基础
- 垃圾回收和性能
- 被动回收
- 滞后时间模式
- 针对共享 Web 承载优化
- 垃圾回收通知
- 应用程序域资源监控
- 弱引用
- 泛型类型(泛型)概述
- 委托和 lambda
- LINQ(语言集成查询)
- 常规类型系统和公共语言规范
- 异步概述
- 深入了解异步
- 异步编程模式
- 基于任务的异步模式 (TAP)
- 实现基于任务的异步模式
- 使用基于任务的异步模式
- 与其他异步模式和类型互操作
- 基于事件的异步模式 (EAP)
- 使用基于事件的异步模式进行多线程编程
- 基于事件的异步模式概述
- 实现基于事件的异步模式
- 实现基于事件的异步模式的最佳做法
- 确定何时实现基于事件的异步模式
- 演练:实现支持基于事件的异步模式的组件
- 演练:实现支持基于事件的异步模式的组件
- 如何:实现基于事件的异步模式的客户端
- 如何:使用支持基于事件的异步模式的组件
- 异步编程模型 (APM)
- 使用 IAsyncResult 调用异步方法
- 使用 AsyncWaitHandle 阻止应用程序的执行
- 通过结束异步操作来阻止应用程序执行
- 轮询异步操作的状态
- 使用 AsyncCallback 委托结束异步操作
- 使用 AsyncCallback 委托和状态对象
- 使用委托进行异步编程
- 使用异步方式调用同步方法
- 本机互操作性
- 集合和数据结构
- .NET Framework 中的数字
- 日期、时间和时区
- 时区概述
- 在 DateTime、DateTimeOffset、TimeSpan 和 TimeZoneInfo 之间进行选择
- 查找本地系统上定义的时区
- 如何: 枚举计算机上存在的时区
- 如何: 访问预定义的 UTC 和当地时间区域对象
- 如何: 实例化 TimeZoneInfo 对象
- 实例化 DateTimeOffset 对象
- 如何: 创建不带调整规则的时区
- 如何: 创建带有调整规则的时区
- 保存和还原时区
- 如何: 将时区保存到嵌入的资源
- 如何: 从嵌入的资源还原时区
- 使用日历
- 使用日期和时间执行算术运算
- 如何: 在日期和时间运算中使用时区
- 在 DateTime 与 DateTimeOffset 之间进行转换
- 在各时区之间转换时间
- 如何: 解决不明确的时间
- 如何: 让用户解决不明确的时间
- 处理和引发事件
- 如何:引发和使用事件
- 如何:使用事件属性处理多个事件
- 如何:在 Web 窗体应用程序中使用事件
- 观察程序设计模式
- 观察程序设计模式最佳做法
- 如何:实现提供程序
- 如何:实现观察程序
- 托管执行过程
- 元数据和自描述组件
- 在 .NET Framework 中构建控制台应用程序
- .NET Framework 中的并行处理和并发
- .NET Framework 应用程序要点
- 文件和流 I/O
- 对 .NET Framework 应用程序进行全球化和本地化
- 全球化
- 本地化评审
- 本地化
- 不区分区域性的字符串操作
- 执行不区分区域性的字符串操作
- 执行不区分区域性的字符串比较
- 执行不区分区域性的大小写更改
- 在集合中执行不区分区域性的字符串操作
- 在数组中执行不区分区域性的字符串操作
- 开发全球通用应用程序的最佳做法
- 利用特性扩展元数据
- 应用特性
- 编写自定义特性
- 检索存储在特性中的信息
- 框架设计准则
- 命名准则
- 大小写约定
- 通用命名约定
- 程序集和 DLL 的名称
- 命名空间的名称
- 类、结构和接口的名称
- 类型成员的名称
- 命名参数
- 命名资源
- 类型设计准则
- 在类和结构之间选择
- 抽象类设计
- 静态类设计
- 接口设计
- 结构设计
- 枚举设计
- 嵌套类型
- 成员设计准则
- 成员重载
- 属性设计
- 构造函数设计
- 事件设计
- 字段设计
- 扩展方法
- 运算符重载
- 参数设计
- 扩展性设计
- 未密封类
- 受保护的成员
- 事件和回调
- 虚成员
- 抽象(抽象类型和接口)
- 用于实现抽象的基类
- 密封
- 异常设计准则
- 异常引发
- 使用标准异常类型
- 异常和性能
- 使用准则
- 数组
- 特性
- 集合准则
- 序列化
- System.Xml 使用情况
- 相等运算符
- 常见设计模式
- 依赖项属性
- 释放模式
- XML 文档和数据
- XML 处理选项
- 内存中 XML 数据处理
- 使用 DOM 模型处理 XML 数据
- XML 文档对象模型 (DOM)
- XML 节点类型
- XML 文档对象模型 (DOM) 层次结构
- 将对象层次结构映射到 XML 数据
- 创建 XML 文档
- 将 XML 文档读入 DOM
- 嵌入到文档中的样式表指令
- 从读取器中加载数据
- 加载 DOM 时的空白和有效空白处理
- 访问 DOM 中的属性
- 将实体声明和实体引用读入 DOM
- 保留实体引用
- 扩展但不保留实体引用
- 将节点插入 XML 文档中
- 在 DOM 中创建新节点
- 为 DOM 中的元素创建新属性
- 创建新节点时的 XML 元素和属性名验证
- 创建新实体引用
- 命名空间对包含元素和属性的新节点的实体引用扩展的影响
- 复制现有节点
- 将现有节点从一个文档复制到另一个文档
- 复制文档片段
- 移除 XML 文档中的节点、内容和值
- 从 DOM 中移除节点
- 移除 DOM 中元素节点的属性
- 移除 DOM 中的节点内容
- 修改 XML 文档中的节点、内容和值
- 在 DOM 中验证 XML 文档
- 保存和写出文档
- 使用 XPath 导航选择节点
- 解析外部资源
- 使用 XmlNameTable 的对象比较
- NamedNodeMap 和 NodeList 中的节点集合
- 按名称或索引检索未排序节点
- 按索引检索已排序节点
- NodeList 和 NamedNodeMap 的动态更新
- DOM 中的命名空间支持
- DOM 中的命名空间和 DTD
- 更改 XML 文档中的命名空间声明
- 更改命名空间前缀属性
- 使用 mlNodeChangedEventArgs 的 XML 文档中的事件处理
- 扩展 DOM
- 使用 XPath 数据模型处理 XML 数据
- 使用 XPathDocument 和 XmlDocument 读取 XML 数据
- 使用 XPathNavigator 选择、计算和匹配 XML 数据
- 使用 XPathNavigator 选择 XML 数据
- 使用 XPathNavigator 计算 XPath 表达式
- 使用 XPathNavigator 匹配节点
- XPath 查询识别的节点类型
- XPath 查询和命名空间
- 已编译的 XPath 表达式
- XPath 命名空间浏览
- 使用 XPathNavigator 访问 XML 数据
- 使用 XPathNavigator 的节点集定位
- 使用 XPathNavigator 的属性和命名空间节点定位
- 使用 XPathNavigator 提取 XML 数据
- 使用 XPathNavigator 访问强类型 XML 数据
- 用户定义的函数和变量
- 使用 XPathNavigator 编辑 XML 数据
- 使用 XPathNavigator 插入 XML 数据
- 使用 XPathNavigator 修改 XML 数据
- 使用 XPathNavigator 移除 XML 数据
- 使用 XPathNavigator 验证架构
- 使用 LINQ to XML 处理 XML 数据
- XSLT 转换
- 使用 XslCompiledTransform 类
- XslCompiledTransform 类的输入
- XslCompiledTransform 类的输出选项
- 在 XSLT 处理期间解析外部资源
- 扩展 XSLT 样式表
- XSLT 扩展对象
- XSLT 参数
- 使用 msxsl:script 的脚本块
- 可恢复的 XSLT 错误
- 如何:转换节点片断
- 从 XslTransform 类迁移
- 如何:迁移 XslTransform 代码
- XSLT 安全注意事项
- XSLT 编译器 (xsltc.exe)
- 如何:通过使用程序集执行 XSLT 转换
- XslTransform 类的 XSLT 转换
- XslTransform 类中任意行为的实现
- XslTransform 类实现 XSLT 处理器
- XslTransform 的输出
- 不同存储区的 XSLT 转换
- 解析外部 XSLT 样式表和文档
- 样式表参数和扩展对象的 XsltArgumentList
- XSLT 样式表脚本使用<msxsl: script>
- 对 msxsl:node-set() 函数的支持
- 转换中的节点集
- 转换中的结果树片断
- 转换中的 XPathNavigator
- 转换中的 XPathNodeIterator
- XslTransform 的 XPathDocument 输入
- XslTransform 的 XmlDataDocument 输入
- XslTransform 的 XmlDocument 输入
- 使用 XML 架构
- XML 架构对象模型 (SOM)
- XML 架构对象模型概述
- 读写 XML 架构
- 生成 XML 架构
- 遍历 XML 架构
- 编辑 XML 架构
- 包含或导入 XML 架构
- 用于编译架构的 XmlSchemaSet
- 后架构编译信息集
- 使用 XmlSchemaSet 进行 XML 架构 (XSD) 验证
- XmlSchemaCollection 架构编译
- 使用 XmlSchemaCollection 进行 XDR 验证
- 使用 XmlSchemaCollection 进行 XML 架构 (XSD) 验证
- XmlSchemaValidator 基于推送的验证
- 推断 XML 架构
- 从 XML 文档推断架构
- 推断架构节点类型和结构的规则
- 推断简单类型的规则
- 关系数据和 ADO.NET 的 XML 集成
- 管理 XML 文档中的命名空间
- System.Xml 类中的类型支持
- 将 XML 数据类型映射到 CLR 类型
- XML 类型支持实现说明
- XML 数据类型的转换
- 将字符串转换为 .NET Framework 数据类型
- 将 .NET Framework 类型转换为字符串
- 托管线程处理
- 托管线程处理基本知识
- 线程与线程处理
- 托管线程中的异常
- 为多线程处理同步数据
- 托管线程状态
- 前台和后台线程
- Windows 中的托管和非托管线程处理
- Thread.Suspend、垃圾回收和安全点
- 线程本地存储区:线程相关的静态字段和数据槽
- 托管线程中的取消
- 如何:通过轮询侦听取消请求
- 如何:注册取消请求的回调
- 如何:侦听具有等待句柄的取消请求
- 如何:侦听多个取消请求
- 使用线程和线程处理
- 启动时创建线程并传递数据
- 暂停和继续线程
- 销毁线程
- 调度线程
- 以协作方式取消线程
- 托管线程处理的最佳做法
- 线程处理对象和功能
- 托管线程池
- 计时器
- EventWaitHandle、AutoResetEvent、CountdownEvent、ManualResetEvent
- EventWaitHandle
- AutoResetEvent
- ManualResetEvent 和 ManualResetEventSlim
- CountdownEvent
- Mutexes
- 互锁操作
- 读取器/编写器锁
- Semaphore 和 SemaphoreSlim
- 同步基元概述
- 屏障 (.NET Framework)
- 如何:使用屏障来使并发操作保持同步
- SpinLock
- 如何:使用 SpinLock 进行低级别同步
- 如何:在 SpinLock 中启用线程跟踪模式
- SpinWait
- 如何:使用 SpinWait 实现两阶段等待操作
- .NET 中的并行编程
- 任务并行库 (TPL)
- 数据并行(任务并行库)
- 如何:编写简单的 Parallel.For 循环
- 如何:编写简单的 Parallel.ForEach 循环
- 如何:编写具有线程局部变量的 Parallel.For 循环
- 如何:编写具有线程局部变量的 Parallel.ForEach 循环
- 如何:取消 Parallel.For 或 ForEach Loop
- 如何:处理并行循环中的异常
- 如何:加快小型循环体的速度
- 如何:使用并行类循环访问文件目录
- 基于任务的异步编程
- 使用延续任务来链接任务
- 已附加和已分离的子任务
- 任务取消
- 异常处理(任务并行库)
- 如何:使用 Parallel.Invoke 来执行并行操作
- 如何:从任务中返回值
- 如何:取消任务及其子级
- 如何:创建预先计算的任务
- 如何:使用并行任务遍历二叉树
- 如何:解除嵌套任务的包装
- 如何:防止子任务附加到其父任务
- 数据流(任务并行库)
- 如何:将消息写入数据流块和从数据流块读取消息
- 如何:实现制造者-使用者数据流模式
- 如何:在数据流块收到数据时执行操作
- 演练:创建数据流管道
- 如何:取消链接数据流块
- 演练:在 Windows 窗体应用程序中使用数据流
- 如何:取消数据流块
- 演练:创建自定义数据流块类型
- 如何:使用 JoinBlock 从多个源读取数据
- 如何:指定数据流块中的并行度
- 如何:在数据流块中指定任务计划程序
- 演练:使用 BatchBlock 和 BatchedJoinBlock 提高效率
- 将 TPL 用于其他异步模式
- TPL 和传统 .NET Framework 异步编程
- 如何:在任务中包装 EAP 模式
- 数据并行和任务并行中的潜在缺陷
- 并行 LINQ (PLINQ)
- PLINQ 介绍
- 了解 PLINQ 中的加速
- PLINQ 中的顺序保留
- PLINQ 中的合并选项
- PLINQ 的潜在缺陷
- 如何:创建并执行简单的 PLINQ 查询
- 如何:在 PLINQ 查询中控制排序
- 如何:合并并行和顺序 LINQ 查询
- 如何:处理 PLINQ 查询中的异常
- 如何:取消 PLINQ 查询
- 如何:编写自定义 PLINQ 聚合函数
- 如何:在 PLINQ 中指定执行模式
- 如何:在 PLINQ 中指定合并选项
- 如何:使用 PLINQ 循环访问文件目录
- 如何:衡量 PLINQ 查询性能
- PLINQ 数据示例
- 用于并行编程的数据结构
- 并行诊断工具
- PLINQ 和 TPL 的自定义分区程序
- 如何:实现动态分区
- 如何:实现静态分区的分区程序
- PLINQ 和 TPL 中的 Lambda 表达式
- 其他阅读材料(并行编程)
- .NET Framework 中的安全性
- 安全性的基础概念
- 基于角色的安全性
- 主体和标识对象
- 如何:创建 WindowsPrincipal 对象
- 如何:创建 GenericPrincipal 和 GenericIdentity 对象
- 替换 Principal 对象
- 模拟与恢复
- .NET Framework 加密模型
- 加密服务
- 生成加密和解密的密钥
- 如何:将非对称密钥存储在密钥容器中
- 加密数据
- 解密数据
- 加密签名
- 使用哈希代码确保数据完整性
- 创建加密方案
- 如何:用对称密钥对 XML 元素进行加密
- 如何:用对称密钥对 XML 元素进行解密
- 如何:用非对称密钥对 XML 元素进行加密
- 如何:用非对称密钥对 XML 元素进行解密
- 如何:用 X.509 证书对 XML 元素进行加密
- 如何:用 X.509 证书对 XML 元素进行解密
- 如何:使用数字签名为 XML 文档签名
- 如何:验证 XML 文档的数字签名
- 如何:使用数据保护
- 如何:访问硬件加密设备
- 演练:创建加密应用程序
- 代码安全维护指南
- 保护状态数据
- 安全性和用户输入
- 安全和争用条件
- 安全性和进行中的代码生成
- .NET 中的序列化
- 序列化帮助主题
- 二进制序列化
- 序列化概念
- 基本序列化
- 有选择的序列化
- 自定义序列化
- 序列化过程中的步骤
- 版本容错序列化
- 序列化准则
- 如何:对序列化数据进行分块
- 如何: 确定是否可序列化的标准.NET 对象
- 请参阅
- 请参阅
- XML 和 SOAP 序列化
- 如何:控制派生类的序列化
- XML 序列化简介
- 如何:反序列化对象
- XML 序列化示例
- XML 架构定义工具和 XML 序列化
- How to: Use the XML Schema Definition Tool to Generate Classes and XML Schema Documents
- 使用属性控制 XML 序列化
- 用来控制 XML 序列化的属性
- 如何:指定 XML 流的替代元素名称
- 如何:序列化对象
- 如何:限定 XML 元素和 XML 属性名
- 使用 XML Web services 进行 XML 序列化
- 如何:将对象序列化为 SOAP 编码的 XML 流
- 如何:重写编码的 SOAP XML 序列化
- 用来控制编码的 SOAP 序列化的属性
- <system.xml.serialization> 元素
- <dateTimeSerialization> 元素
- <schemaImporterExtensions> 元素
- <xmlSerializer> 元素
- 序列化工具
- XML 序列化程序生成器工具 (Sgen.exe)
- XML Schema Definition Tool (Xsd.exe)
- .NET Framework 的序列化示例
- 基本序列化技术示例
- 使用 XmlSerializer 自定义序列化顺序
- SchemaImporterExtension 技术示例
- 版本容错序列化技术示例
- Web 服务泛型序列化技术示例
- Web 服务 IXmlSerializable 技术示例
- 使用 .NET Framework 针对多个平台开发
- 使用可移植类库的跨平台开发
- 将可移植类库与模型-视图-视图模型配合使用
- 面向多个平台的库的应用程序资源
- .NET Framework 对 Windows 应用商店应用程序和 Windows 运行时的支持情况
- 向 Windows 运行时传递 URI
- WindowsRuntimeStreamExtensions.AsRandomAccessStream(System.IO.Stream) 方法
.NET Framework 中的类型转换
每个值都有与之关联的类型,此类型定义分配给该值的空间大小、它可以具有的可能值的范围以及它可以提供的成员等属性。 许多值可以表示为多种类型。 例如,值 4 可以表示为整数或浮点值。 类型转换可以创建一个等同于旧类型值的新类型值,但却不必保留原始对象的恒等值(或精确值)。
.NET Framework 自动支持以下转换:
- 从派生类转换为基类。 例如,这意味着可将任何类或结构的实例转换为 Object 实例。 此转换不需要强制转换或转换运算符。
- 从基类转换回原始的派生类。 在 C# 中,此转换需要强制转换运算符。 在 Visual Basic 中,如果
Option Strict
处于开启状态,则它需要CType
运算符。 - 从实现接口的类型转换为表示该接口的接口对象。 此转换不需要强制转换或转换运算符。
- 从接口对象转换回实现该接口的原始类型。 在 C# 中,此转换需要强制转换运算符。 在 Visual Basic 中,如果
Option Strict
处于开启状态,则它需要CType
运算符。
除这些自动转换外,.NET Framework 还提供支持自定义类型转换的多种功能。 这些要求包括:
Implicit
运算符,该运算符定义类型之间可用的扩大转换。 有关详细信息,请参阅 使用隐式运算符的隐式转换 部分。Explicit
运算符,该运算符定义类型之间可用的收缩转换。 有关详细信息,请参阅 使用显式运算符的显式转换 部分。- IConvertible 接口,该接口定义到 .NET Framework 每个基数据类型的转换。 有关详细信息,请参阅 IConvertible 接口 部分。
- Convert 类,该类提供了一组方法来实现 IConvertible 接口中的方法。 有关详细信息,请参阅 Convert 类 部分。
- TypeConverter 类,该类是一个基类,可以扩展该类以支持指定的类型到任何其他类型的转换。 有关详细信息,请参阅 TypeConverter 类 部分。
使用隐式运算符的隐式转换
扩大转换涉及从现有类型的值创建一个新值,该现有类型比目标类型具有限制性更强的范围或限制性更强的成员列表。 扩大转换不会导致数据丢失(但可能导致精度损失)。 由于不会丢失数据,因此编译器可以隐式或透明地处理转换,无需使用显式转换方法或强制转换运算符。
备注
虽然执行隐式转换的代码可以调用转换方法或使用强制转换运算符,但支持隐式转换的编译器不需要调用转换方法或使用强制转换运算符。
例如, Decimal 类型支持从 Byte 、 Char 、 Int16 、 Int32 、 Int64 、 SByte 、 UInt16 、 UInt32 和 UInt64 值进行的隐式转换。 下面的示例通过为 Decimal 变量赋值演示了其中的一些隐式转换。
byte byteValue = 16;
short shortValue = -1024;
int intValue = -1034000;
long longValue = 1152921504606846976;
ulong ulongValue = UInt64.MaxValue;
decimal decimalValue;
decimalValue = byteValue;
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
byteValue.GetType().Name, decimalValue);
decimalValue = shortValue;
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
shortValue.GetType().Name, decimalValue);
decimalValue = intValue;
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
intValue.GetType().Name, decimalValue);
decimalValue = longValue;
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
longValue.GetType().Name, decimalValue);
decimalValue = ulongValue;
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
longValue.GetType().Name, decimalValue);
// The example displays the following output:
// After assigning a Byte value, the Decimal value is 16.
// After assigning a Int16 value, the Decimal value is -1024.
// After assigning a Int32 value, the Decimal value is -1034000.
// After assigning a Int64 value, the Decimal value is 1152921504606846976.
// After assigning a Int64 value, the Decimal value is 18446744073709551615.
Dim byteValue As Byte = 16
Dim shortValue As Short = -1024
Dim intValue As Integer = -1034000
Dim longValue As Long = CLng(1024^6)
Dim ulongValue As ULong = ULong.MaxValue
Dim decimalValue As Decimal
decimalValue = byteValue
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
byteValue.GetType().Name, decimalValue)
decimalValue = shortValue
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
shortValue.GetType().Name, decimalValue)
decimalValue = intValue
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
intValue.GetType().Name, decimalValue)
decimalValue = longValue
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
longValue.GetType().Name, decimalValue)
decimalValue = ulongValue
Console.WriteLine("After assigning a {0} value, the Decimal value is {1}.",
longValue.GetType().Name, decimalValue)
' The example displays the following output:
' After assigning a Byte value, the Decimal value is 16.
' After assigning a Int16 value, the Decimal value is -1024.
' After assigning a Int32 value, the Decimal value is -1034000.
' After assigning a Int64 value, the Decimal value is 1152921504606846976.
' After assigning a Int64 value, the Decimal value is 18446744073709551615.
如果特定语言编译器支持自定义运算符,则您还可以在自己的自定义类型中定义隐式转换。 下面的示例提供了一个名为 ByteWithSign
的有符号字节数据类型的分部实现,该分部实现使用符号数值表示法。 它支持 Byte 和 SByte 值到 ByteWithSign
值的隐式转换。
public struct ByteWithSign
{
private SByte signValue;
private Byte value;
public static implicit operator ByteWithSign(SByte value)
{
ByteWithSign newValue;
newValue.signValue = (SByte) Math.Sign(value);
newValue.value = (byte) Math.Abs(value);
return newValue;
}
public static implicit operator ByteWithSign(Byte value)
{
ByteWithSign newValue;
newValue.signValue = 1;
newValue.value = value;
return newValue;
}
public override string ToString()
{
return (signValue * value).ToString();
}
}
Public Structure ByteWithSign
Private signValue As SByte
Private value As Byte
Public Overloads Shared Widening Operator CType(value As SByte) As ByteWithSign
Dim newValue As ByteWithSign
newValue.signValue = CSByte(Math.Sign(value))
newValue.value = CByte(Math.Abs(value))
Return newValue
End Operator
Public Overloads Shared Widening Operator CType(value As Byte) As ByteWithSign
Dim NewValue As ByteWithSign
newValue.signValue = 1
newValue.value = value
Return newValue
End Operator
Public Overrides Function ToString() As String
Return (signValue * value).ToString()
End Function
End Structure
然后,客户端代码可以声明一个 ByteWithSign
变量,并为该变量赋予 Byte 和 SByte 值,而无需执行任何显式转换或使用任何强制转换运算符,如下面的示例所示。
SByte sbyteValue = -120;
ByteWithSign value = sbyteValue;
Console.WriteLine(value);
value = Byte.MaxValue;
Console.WriteLine(value);
// The example displays the following output:
// -120
// 255
Dim sbyteValue As SByte = -120
Dim value As ByteWithSign = sbyteValue
Console.WriteLine(value.ToString())
value = Byte.MaxValue
Console.WriteLine(value.ToString())
' The example displays the following output:
' -120
' 255
使用显式运算符的显式转换
收缩转换涉及从现有类型的值创建一个新值,该现有类型比目标类型具有更大的范围和更大的成员列表。 由于收缩转换可以导致数据丢失,因此编译器通常需要通过调用转换方法或使用强制转换运算符来进行显式转换。 也就是说,必须在开发人员代码中显式处理收缩转换。
备注
收缩转换之所以需要使用转换方法或强制转换运算符,主要是为提醒开发人员可能会丢失数据或引发 OverflowException ,以便可以在代码中对其进行处理。 但是,有些编译器可以放宽此要求。 例如,在 Visual Basic 中,如果 Option Strict
关闭(其默认设置),则 Visual Basic 编译器会尝试隐式执行收缩转换。
例如, UInt32 、 Int64 和 UInt64 数据类型均具有超过 Int32 数据类型的范围,如下表所示。
类型 | 与 Int32 范围的比较 |
---|---|
Int64 | Int64.MaxValue 大于 Int32.MaxValue ; Int64.MinValue 小于 Int32.MinValue (即比后者具有更大的负范围)。 |
UInt32 | UInt32.MaxValue 大于 Int32.MaxValue 。 |
UInt64 | UInt64.MaxValue 大于 Int32.MaxValue 。 |
为了处理这种收缩转换,.NET Framework 允许类型定义 Explicit
运算符。 然后,各种语言编译器可以实现使用自己的语法或属于此运算符 Convert 可以调用类来执行转换。 (有关 Convert 类的详细信息,请参阅本主题后面部分的 Convert 类 。)下面的示例演示如何使用语言功能来处理这些可能超出范围的整数值到 Int32 值的显式转换。
long number1 = int.MaxValue + 20L;
uint number2 = int.MaxValue - 1000;
ulong number3 = int.MaxValue;
int intNumber;
try {
intNumber = checked((int) number1);
Console.WriteLine("After assigning a {0} value, the Integer value is {1}.",
number1.GetType().Name, intNumber);
}
catch (OverflowException) {
if (number1 > int.MaxValue)
Console.WriteLine("Conversion failed: {0} exceeds {1}.",
number1, int.MaxValue);
else
Console.WriteLine("Conversion failed: {0} is less than {1}.",
number1, int.MinValue);
}
try {
intNumber = checked((int) number2);
Console.WriteLine("After assigning a {0} value, the Integer value is {1}.",
number2.GetType().Name, intNumber);
}
catch (OverflowException) {
Console.WriteLine("Conversion failed: {0} exceeds {1}.",
number2, int.MaxValue);
}
try {
intNumber = checked((int) number3);
Console.WriteLine("After assigning a {0} value, the Integer value is {1}.",
number3.GetType().Name, intNumber);
}
catch (OverflowException) {
Console.WriteLine("Conversion failed: {0} exceeds {1}.",
number1, int.MaxValue);
}
// The example displays the following output:
// Conversion failed: 2147483667 exceeds 2147483647.
// After assigning a UInt32 value, the Integer value is 2147482647.
// After assigning a UInt64 value, the Integer value is 2147483647.
Dim number1 As Long = Integer.MaxValue + 20L
Dim number2 As UInteger = Integer.MaxValue - 1000
Dim number3 As ULong = Integer.MaxValue
Dim intNumber As Integer
Try
intNumber = CInt(number1)
Console.WriteLine("After assigning a {0} value, the Integer value is {1}.",
number1.GetType().Name, intNumber)
Catch e As OverflowException
If number1 > Integer.MaxValue Then
Console.WriteLine("Conversion failed: {0} exceeds {1}.",
number1, Integer.MaxValue)
Else
Console.WriteLine("Conversion failed: {0} is less than {1}.\n",
number1, Integer.MinValue)
End If
End Try
Try
intNumber = CInt(number2)
Console.WriteLine("After assigning a {0} value, the Integer value is {1}.",
number2.GetType().Name, intNumber)
Catch e As OverflowException
Console.WriteLine("Conversion failed: {0} exceeds {1}.",
number2, Integer.MaxValue)
End Try
Try
intNumber = CInt(number3)
Console.WriteLine("After assigning a {0} value, the Integer value is {1}.",
number3.GetType().Name, intNumber)
Catch e As OverflowException
Console.WriteLine("Conversion failed: {0} exceeds {1}.",
number1, Integer.MaxValue)
End Try
' The example displays the following output:
' Conversion failed: 2147483667 exceeds 2147483647.
' After assigning a UInt32 value, the Integer value is 2147482647.
' After assigning a UInt64 value, the Integer value is 2147483647.
显式转换在不同的语言中可能会产生不同的结果,并且这些结果可能因对应的 Convert 方法所返回的值而异。 例如,如果将 Double 值 12.63251 转换为 Int32 ,则 Visual Basic CInt
方法和 .NET Framework Convert.ToInt32(Double) 方法会对 Double 进行舍入以返回值 13,而 C# (int)
运算符会截断 Double 以返回值 12。 类似地,C# (int)
运算符不支持从布尔值到整数的转换,而 Visual Basic CInt
方法会将值 true
转换为 -1。 另一方面, Convert.ToInt32(Boolean) 方法将值 true
转换为 1。
大多数编译器允许以有检查或无检查的方式执行显式转换。 当执行有检查转换时,如果被转换类型的值超出了目标类型的范围,则会引发 OverflowException 。 在相同条件下执行无检查转换时,转换可能不会引发异常,但无法确定确切的行为,并且可能产生不正确的值。
备注
在 C# 中,可将 checked
关键字与强制转换运算符一起使用来执行有检查转换,也可通过指定 /checked+
编译器选项来执行有检查转换。 反过来,可将 unchecked
关键字与强制转换运算符一起使用来执行无检查转换,或者通过指定 /checked-
编译器选项来执行无检查转换。 默认情况下,显式转换将为无检查转换。 在 Visual Basic 中,通过清除项目的 高级编译器设置
对话框中的 不做整数溢出检查
复选框或指定 /removeintchecks-
编译器选项,可以执行有检查转换。 反之,通过选中项目的 高级编译器设置
对话框中的 不做整数溢出检查
复选框,或者指定 /removeintchecks+
编译器选项,可以执行无检查转换。 默认情况下,显式转换将为有检查转换。
下面的 C# 示例使用 checked
和 unchecked
关键字阐释了将 Byte 范围外的值转换为 Byte 时的行为差异。 有检查转换会引发异常,但无检查转换会向 Byte.MaxValue 变量赋予 Byte 。
int largeValue = Int32.MaxValue;
byte newValue;
try {
newValue = unchecked((byte) largeValue);
Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.",
largeValue.GetType().Name, largeValue,
newValue.GetType().Name, newValue);
}
catch (OverflowException) {
Console.WriteLine("{0} is outside the range of the Byte data type.",
largeValue);
}
try {
newValue = checked((byte) largeValue);
Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.",
largeValue.GetType().Name, largeValue,
newValue.GetType().Name, newValue);
}
catch (OverflowException) {
Console.WriteLine("{0} is outside the range of the Byte data type.",
largeValue);
}
// The example displays the following output:
// Converted the Int32 value 2147483647 to the Byte value 255.
// 2147483647 is outside the range of the Byte data type.
如果特定语言编译器支持自定义重载运算符,您还可以在自己的自定义类型中定义显式转换。 下面的示例提供了一个名为 ByteWithSign
的有符号字节数据类型的分部实现,该分部实现使用符号数值表示法。 它支持 Int32 和 UInt32 值到 ByteWithSign
值的显式转换。
public struct ByteWithSign
{
private SByte signValue;
private Byte value;
private const byte MaxValue = byte.MaxValue;
private const int MinValue = -1 * byte.MaxValue;
public static explicit operator ByteWithSign(int value)
{
// Check for overflow.
if (value > ByteWithSign.MaxValue || value < ByteWithSign.MinValue)
throw new OverflowException(String.Format("'{0}' is out of range of the ByteWithSign data type.",
value));
ByteWithSign newValue;
newValue.signValue = (SByte) Math.Sign(value);
newValue.value = (byte) Math.Abs(value);
return newValue;
}
public static explicit operator ByteWithSign(uint value)
{
if (value > ByteWithSign.MaxValue)
throw new OverflowException(String.Format("'{0}' is out of range of the ByteWithSign data type.",
value));
ByteWithSign newValue;
newValue.signValue = 1;
newValue.value = (byte) value;
return newValue;
}
public override string ToString()
{
return (signValue * value).ToString();
}
}
Public Structure ByteWithSign
Private signValue As SByte
Private value As Byte
Private Const MaxValue As Byte = Byte.MaxValue
Private Const MinValue As Integer = -1 * Byte.MaxValue
Public Overloads Shared Narrowing Operator CType(value As Integer) As ByteWithSign
' Check for overflow.
If value > ByteWithSign.MaxValue Or value < ByteWithSign.MinValue Then
Throw New OverflowException(String.Format("'{0}' is out of range of the ByteWithSign data type.", value))
End If
Dim newValue As ByteWithSign
newValue.signValue = CSByte(Math.Sign(value))
newValue.value = CByte(Math.Abs(value))
Return newValue
End Operator
Public Overloads Shared Narrowing Operator CType(value As UInteger) As ByteWithSign
If value > ByteWithSign.MaxValue Then
Throw New OverflowException(String.Format("'{0}' is out of range of the ByteWithSign data type.", value))
End If
Dim NewValue As ByteWithSign
newValue.signValue = 1
newValue.value = CByte(value)
Return newValue
End Operator
Public Overrides Function ToString() As String
Return (signValue * value).ToString()
End Function
End Structure
然后,客户端代码可以声明一个 ByteWithSign
变量,并为该变量赋予 Int32 和 UInt32 值(如果赋值中包括一个强制转换运算符或转换方法),如下面的示例所示。
ByteWithSign value;
try {
int intValue = -120;
value = (ByteWithSign) intValue;
Console.WriteLine(value);
}
catch (OverflowException e) {
Console.WriteLine(e.Message);
}
try {
uint uintValue = 1024;
value = (ByteWithSign) uintValue;
Console.WriteLine(value);
}
catch (OverflowException e) {
Console.WriteLine(e.Message);
}
// The example displays the following output:
// -120
// '1024' is out of range of the ByteWithSign data type.
Dim value As ByteWithSign
Try
Dim intValue As Integer = -120
value = CType(intValue, ByteWithSign)
Console.WriteLine(value)
Catch e As OverflowException
Console.WriteLine(e.Message)
End Try
Try
Dim uintValue As UInteger = 1024
value = CType(uintValue, ByteWithSign)
Console.WriteLine(value)
Catch e As OverflowException
Console.WriteLine(e.Message)
End Try
' The example displays the following output:
' -120
' '1024' is out of range of the ByteWithSign data type.
IConvertible 接口
为了支持任意类型到公共语言运行时基类型的转换,.NET Framework 提供了 IConvertible 接口。 需要使用实现类型以提供以下方法:
- 一个返回实现类型的 TypeCode 的方法。
- 用于将实现类型转换为公共语言运行时的每一种基类型( Boolean 、 Byte 、 DateTime 、 Decimal 和 Double 等)的各种方法。
- 一个用于将实现类型的实例转换为另一个指定类型的通用转换方法。 不支持的转换应引发 InvalidCastException 。
公共语言运行时的每一种基类型(即 Boolean 、 Byte 、 Char 、 DateTime 、 Decimal 、 Double 、 Int16 、 Int32 、 Int64 、 SByte 、 Single 、 String 、 UInt16 、 UInt32 和 UInt64 )以及 DBNull 和 Enum 类型都可以实现 IConvertible 接口。 但是,这些是显式接口实现;因此只能通过 IConvertible 接口变量来调用转换方法,如下面的示例所示。 此示例将一个 Int32 值转换为其等效的 Char 值。
int codePoint = 1067;
IConvertible iConv = codePoint;
char ch = iConv.ToChar(null);
Console.WriteLine("Converted {0} to {1}.", codePoint, ch);
Dim codePoint As Integer = 1067
Dim iConv As IConvertible = codePoint
Dim ch As Char = iConv.ToChar(Nothing)
Console.WriteLine("Converted {0} to {1}.", codePoint, ch)
对转换方法的接口(而不是实现类型)调用转换方法的要求使显式接口实现成为一种代价相对较大的操作。 因此,在公共语言运行时基类型之间进行转换时,建议您调用 Convert 类的适当成员。 有关详细信息,请参阅下一部分 Convert 类 。
备注
除了 IConvertible 提供的 Convert 接口和 .NET Framework 类,各种语言还可能会提供其他方法来执行转换。 例如,C# 使用强制转换运算符;Visual Basic 使用编译器实现的转换函数,例如 CType
、 CInt
和 DirectCast
。
大多数情况下, IConvertible 接口设计为支持 .NET Framework 中基类型之间的转换。 但是,通过自定义类型也可以实现该接口,以便支持该类型到其他自定义类型的转换。 有关详细信息,请参阅本主题后面的 使用 ChangeType 方法的自定义转换 部分。
Convert 类
虽然可以调用每个基类型的 IConvertible 接口实现来执行类型转换,但从一种基类型转换为另一种基类型时,建议您调用 System.Convert 类的方法,这种方式与语言无关。 此外, Convert.ChangeType(Object, Type, IFormatProvider) 方法还可用于从一个指定的自定义类型转换为另一种类型。
基类型之间的转换
Convert 类提供了一种与语言无关的方式来执行基类型之间的转换,并且该类可用于面向公共语言运行时的所有语言。 它为扩大转换和收缩转换提供了一组完整的方法,并且会对不支持的转换(例如 InvalidCastException 值到整数值的转换)引发 DateTime 。 收缩转换是在已检查的上下文中执行的,如果转换失败,将引发 OverflowException 。
重要
由于 Convert 类包含用于转换为每个基类型和从每个基类型进行转换的方法,因此不再需要调用每个基类型的 IConvertible 显式接口实现。
下面的示例演示如何使用 System.Convert 类来执行 .NET Framework 基类型之间的多种扩大转换和收缩转换。
// Convert an Int32 value to a Decimal (a widening conversion).
int integralValue = 12534;
decimal decimalValue = Convert.ToDecimal(integralValue);
Console.WriteLine("Converted the {0} value {1} to " +
"the {2} value {3:N2}.",
integralValue.GetType().Name,
integralValue,
decimalValue.GetType().Name,
decimalValue);
// Convert a Byte value to an Int32 value (a widening conversion).
byte byteValue = Byte.MaxValue;
int integralValue2 = Convert.ToInt32(byteValue);
Console.WriteLine("Converted the {0} value {1} to " +
"the {2} value {3:G}.",
byteValue.GetType().Name,
byteValue,
integralValue2.GetType().Name,
integralValue2);
// Convert a Double value to an Int32 value (a narrowing conversion).
double doubleValue = 16.32513e12;
try {
long longValue = Convert.ToInt64(doubleValue);
Console.WriteLine("Converted the {0} value {1:E} to " +
"the {2} value {3:N0}.",
doubleValue.GetType().Name,
doubleValue,
longValue.GetType().Name,
longValue);
}
catch (OverflowException) {
Console.WriteLine("Unable to convert the {0:E} value {1}.",
doubleValue.GetType().Name, doubleValue);
}
// Convert a signed byte to a byte (a narrowing conversion).
sbyte sbyteValue = -16;
try {
byte byteValue2 = Convert.ToByte(sbyteValue);
Console.WriteLine("Converted the {0} value {1} to " +
"the {2} value {3:G}.",
sbyteValue.GetType().Name,
sbyteValue,
byteValue2.GetType().Name,
byteValue2);
}
catch (OverflowException) {
Console.WriteLine("Unable to convert the {0} value {1}.",
sbyteValue.GetType().Name, sbyteValue);
}
// The example displays the following output:
// Converted the Int32 value 12534 to the Decimal value 12,534.00.
// Converted the Byte value 255 to the Int32 value 255.
// Converted the Double value 1.632513E+013 to the Int64 value 16,325,130,000,000.
// Unable to convert the SByte value -16.
' Convert an Int32 value to a Decimal (a widening conversion).
Dim integralValue As Integer = 12534
Dim decimalValue As Decimal = Convert.ToDecimal(integralValue)
Console.WriteLine("Converted the {0} value {1} to the {2} value {3:N2}.",
integralValue.GetType().Name,
integralValue,
decimalValue.GetType().Name,
decimalValue)
' Convert a Byte value to an Int32 value (a widening conversion).
Dim byteValue As Byte = Byte.MaxValue
Dim integralValue2 As Integer = Convert.ToInt32(byteValue)
Console.WriteLine("Converted the {0} value {1} to " +
"the {2} value {3:G}.",
byteValue.GetType().Name,
byteValue,
integralValue2.GetType().Name,
integralValue2)
' Convert a Double value to an Int32 value (a narrowing conversion).
Dim doubleValue As Double = 16.32513e12
Try
Dim longValue As Long = Convert.ToInt64(doubleValue)
Console.WriteLine("Converted the {0} value {1:E} to " +
"the {2} value {3:N0}.",
doubleValue.GetType().Name,
doubleValue,
longValue.GetType().Name,
longValue)
Catch e As OverflowException
Console.WriteLine("Unable to convert the {0:E} value {1}.",
doubleValue.GetType().Name, doubleValue)
End Try
' Convert a signed byte to a byte (a narrowing conversion).
Dim sbyteValue As SByte = -16
Try
Dim byteValue2 As Byte = Convert.ToByte(sbyteValue)
Console.WriteLine("Converted the {0} value {1} to " +
"the {2} value {3:G}.",
sbyteValue.GetType().Name,
sbyteValue,
byteValue2.GetType().Name,
byteValue2)
Catch e As OverflowException
Console.WriteLine("Unable to convert the {0} value {1}.",
sbyteValue.GetType().Name, sbyteValue)
End Try
' The example displays the following output:
' Converted the Int32 value 12534 to the Decimal value 12,534.00.
' Converted the Byte value 255 to the Int32 value 255.
' Converted the Double value 1.632513E+013 to the Int64 value 16,325,130,000,000.
' Unable to convert the SByte value -16.
在某些情况下,尤其是当转换为浮点值和从浮点值进行转换时,转换可能会丢失精度,即使不引发 OverflowException 时也是如此。 下面的示例演示了这种精度丢失。 在第一种情况下, Decimal 值在转换为 Double 后精度降低(有效位减少)。 在第二种情况下, Double 值从 42.72 四舍五入为 43 以完成转换。
double doubleValue;
// Convert a Double to a Decimal.
decimal decimalValue = 13956810.96702888123451471211m;
doubleValue = Convert.ToDouble(decimalValue);
Console.WriteLine("{0} converted to {1}.", decimalValue, doubleValue);
doubleValue = 42.72;
try {
int integerValue = Convert.ToInt32(doubleValue);
Console.WriteLine("{0} converted to {1}.",
doubleValue, integerValue);
}
catch (OverflowException) {
Console.WriteLine("Unable to convert {0} to an integer.",
doubleValue);
}
// The example displays the following output:
// 13956810.96702888123451471211 converted to 13956810.9670289.
// 42.72 converted to 43.
Dim doubleValue As Double
' Convert a Double to a Decimal.
Dim decimalValue As Decimal = 13956810.96702888123451471211d
doubleValue = Convert.ToDouble(decimalValue)
Console.WriteLine("{0} converted to {1}.", decimalValue, doubleValue)
doubleValue = 42.72
Try
Dim integerValue As Integer = Convert.ToInt32(doubleValue)
Console.WriteLine("{0} converted to {1}.",
doubleValue, integerValue)
Catch e As OverflowException
Console.WriteLine("Unable to convert {0} to an integer.",
doubleValue)
End Try
' The example displays the following output:
' 13956810.96702888123451471211 converted to 13956810.9670289.
' 42.72 converted to 43.
列出的扩大转换和收缩转换支持的表 Convert 类,请参阅 类型转换表 。
使用 ChangeType 方法的自定义转换
除了支持到每个基类型的转换外, Convert 类还可用于将一个自定义类型转换为一个或多个预定义类型。 此转换是通过 Convert.ChangeType(Object, Type, IFormatProvider) 方法执行的,而此方法包装了对 IConvertible.ToType 参数的 value
方法的调用。 这意味着 value
参数所表示的对象必须提供 IConvertible 接口的实现。
备注
由于 Convert.ChangeType(Object, Type) 和 Convert.ChangeType(Object, Type, IFormatProvider) 方法使用 Type 对象来指定 value
将转换为的目标类型,因此它们可用于执行对象(其类型在编译时是未知的)的动态转换。 但请注意, IConvertible 的 value
实现必须仍支持此转换。
下面的示例演示 IConvertible 接口的一个可能实现,该实现允许将 TemperatureCelsius
对象转换为 TemperatureFahrenheit
对象,反之亦然。 此示例定义一个基类 Temperature
,该基类实现 IConvertible 接口并重写 Object.ToString 方法。 派生的 TemperatureCelsius
和 TemperatureFahrenheit
类分别重写该基类的 ToType
和 ToString
方法。
using System;
public abstract class Temperature : IConvertible
{
protected decimal temp;
public Temperature(decimal temperature)
{
this.temp = temperature;
}
public decimal Value
{
get { return this.temp; }
set { this.temp = Value; }
}
public override string ToString()
{
return temp.ToString(null as IFormatProvider) + "º";
}
// IConvertible implementations.
public TypeCode GetTypeCode() {
return TypeCode.Object;
}
public bool ToBoolean(IFormatProvider provider) {
throw new InvalidCastException(String.Format("Temperature-to-Boolean conversion is not supported."));
}
public byte ToByte(IFormatProvider provider) {
if (temp < Byte.MinValue || temp > Byte.MaxValue)
throw new OverflowException(String.Format("{0} is out of range of the Byte data type.", temp));
else
return (byte) temp;
}
public char ToChar(IFormatProvider provider) {
throw new InvalidCastException("Temperature-to-Char conversion is not supported.");
}
public DateTime ToDateTime(IFormatProvider provider) {
throw new InvalidCastException("Temperature-to-DateTime conversion is not supported.");
}
public decimal ToDecimal(IFormatProvider provider) {
return temp;
}
public double ToDouble(IFormatProvider provider) {
return (double) temp;
}
public short ToInt16(IFormatProvider provider) {
if (temp < Int16.MinValue || temp > Int16.MaxValue)
throw new OverflowException(String.Format("{0} is out of range of the Int16 data type.", temp));
else
return (short) Math.Round(temp);
}
public int ToInt32(IFormatProvider provider) {
if (temp < Int32.MinValue || temp > Int32.MaxValue)
throw new OverflowException(String.Format("{0} is out of range of the Int32 data type.", temp));
else
return (int) Math.Round(temp);
}
public long ToInt64(IFormatProvider provider) {
if (temp < Int64.MinValue || temp > Int64.MaxValue)
throw new OverflowException(String.Format("{0} is out of range of the Int64 data type.", temp));
else
return (long) Math.Round(temp);
}
public sbyte ToSByte(IFormatProvider provider) {
if (temp < SByte.MinValue || temp > SByte.MaxValue)
throw new OverflowException(String.Format("{0} is out of range of the SByte data type.", temp));
else
return (sbyte) temp;
}
public float ToSingle(IFormatProvider provider) {
return (float) temp;
}
public virtual string ToString(IFormatProvider provider) {
return temp.ToString(provider) + "°";
}
// If conversionType is implemented by another IConvertible method, call it.
public virtual object ToType(Type conversionType, IFormatProvider provider) {
switch (Type.GetTypeCode(conversionType))
{
case TypeCode.Boolean:
return this.ToBoolean(provider);
case TypeCode.Byte:
return this.ToByte(provider);
case TypeCode.Char:
return this.ToChar(provider);
case TypeCode.DateTime:
return this.ToDateTime(provider);
case TypeCode.Decimal:
return this.ToDecimal(provider);
case TypeCode.Double:
return this.ToDouble(provider);
case TypeCode.Empty:
throw new NullReferenceException("The target type is null.");
case TypeCode.Int16:
return this.ToInt16(provider);
case TypeCode.Int32:
return this.ToInt32(provider);
case TypeCode.Int64:
return this.ToInt64(provider);
case TypeCode.Object:
// Leave conversion of non-base types to derived classes.
throw new InvalidCastException(String.Format("Cannot convert from Temperature to {0}.",
conversionType.Name));
case TypeCode.SByte:
return this.ToSByte(provider);
case TypeCode.Single:
return this.ToSingle(provider);
case TypeCode.String:
IConvertible iconv = this;
return iconv.ToString(provider);
case TypeCode.UInt16:
return this.ToUInt16(provider);
case TypeCode.UInt32:
return this.ToUInt32(provider);
case TypeCode.UInt64:
return this.ToUInt64(provider);
default:
throw new InvalidCastException("Conversion not supported.");
}
}
public ushort ToUInt16(IFormatProvider provider) {
if (temp < UInt16.MinValue || temp > UInt16.MaxValue)
throw new OverflowException(String.Format("{0} is out of range of the UInt16 data type.", temp));
else
return (ushort) Math.Round(temp);
}
public uint ToUInt32(IFormatProvider provider) {
if (temp < UInt32.MinValue || temp > UInt32.MaxValue)
throw new OverflowException(String.Format("{0} is out of range of the UInt32 data type.", temp));
else
return (uint) Math.Round(temp);
}
public ulong ToUInt64(IFormatProvider provider) {
if (temp < UInt64.MinValue || temp > UInt64.MaxValue)
throw new OverflowException(String.Format("{0} is out of range of the UInt64 data type.", temp));
else
return (ulong) Math.Round(temp);
}
}
public class TemperatureCelsius : Temperature, IConvertible
{
public TemperatureCelsius(decimal value) : base(value)
{
}
// Override ToString methods.
public override string ToString()
{
return this.ToString(null);
}
public override string ToString(IFormatProvider provider)
{
return temp.ToString(provider) + "°C";
}
// If conversionType is a implemented by another IConvertible method, call it.
public override object ToType(Type conversionType, IFormatProvider provider) {
// For non-objects, call base method.
if (Type.GetTypeCode(conversionType) != TypeCode.Object) {
return base.ToType(conversionType, provider);
}
else
{
if (conversionType.Equals(typeof(TemperatureCelsius)))
return this;
else if (conversionType.Equals(typeof(TemperatureFahrenheit)))
return new TemperatureFahrenheit((decimal) this.temp * 9 / 5 + 32);
else
throw new InvalidCastException(String.Format("Cannot convert from Temperature to {0}.",
conversionType.Name));
}
}
}
public class TemperatureFahrenheit : Temperature, IConvertible
{
public TemperatureFahrenheit(decimal value) : base(value)
{
}
// Override ToString methods.
public override string ToString()
{
return this.ToString(null);
}
public override string ToString(IFormatProvider provider)
{
return temp.ToString(provider) + "°F";
}
public override object ToType(Type conversionType, IFormatProvider provider)
{
// For non-objects, call base methood.
if (Type.GetTypeCode(conversionType) != TypeCode.Object) {
return base.ToType(conversionType, provider);
}
else
{
// Handle conversion between derived classes.
if (conversionType.Equals(typeof(TemperatureFahrenheit)))
return this;
else if (conversionType.Equals(typeof(TemperatureCelsius)))
return new TemperatureCelsius((decimal) (this.temp - 32) * 5 / 9);
// Unspecified object type: throw an InvalidCastException.
else
throw new InvalidCastException(String.Format("Cannot convert from Temperature to {0}.",
conversionType.Name));
}
}
}
Public MustInherit Class Temperature
Implements IConvertible
Protected temp As Decimal
Public Sub New(temperature As Decimal)
Me.temp = temperature
End Sub
Public Property Value As Decimal
Get
Return Me.temp
End Get
Set
Me.temp = Value
End Set
End Property
Public Overrides Function ToString() As String
Return temp.ToString() & "º"
End Function
' IConvertible implementations.
Public Function GetTypeCode() As TypeCode Implements IConvertible.GetTypeCode
Return TypeCode.Object
End Function
Public Function ToBoolean(provider As IFormatProvider) As Boolean Implements IConvertible.ToBoolean
Throw New InvalidCastException(String.Format("Temperature-to-Boolean conversion is not supported."))
End Function
Public Function ToByte(provider As IFormatProvider) As Byte Implements IConvertible.ToByte
If temp < Byte.MinValue Or temp > Byte.MaxValue Then
Throw New OverflowException(String.Format("{0} is out of range of the Byte data type.", temp))
Else
Return CByte(temp)
End If
End Function
Public Function ToChar(provider As IFormatProvider) As Char Implements IConvertible.ToChar
Throw New InvalidCastException("Temperature-to-Char conversion is not supported.")
End Function
Public Function ToDateTime(provider As IFormatProvider) As DateTime Implements IConvertible.ToDateTime
Throw New InvalidCastException("Temperature-to-DateTime conversion is not supported.")
End Function
Public Function ToDecimal(provider As IFormatProvider) As Decimal Implements IConvertible.ToDecimal
Return temp
End Function
Public Function ToDouble(provider As IFormatProvider) As Double Implements IConvertible.ToDouble
Return CDbl(temp)
End Function
Public Function ToInt16(provider As IFormatProvider) As Int16 Implements IConvertible.ToInt16
If temp < Int16.MinValue Or temp > Int16.MaxValue Then
Throw New OverflowException(String.Format("{0} is out of range of the Int16 data type.", temp))
End If
Return CShort(Math.Round(temp))
End Function
Public Function ToInt32(provider As IFormatProvider) As Int32 Implements IConvertible.ToInt32
If temp < Int32.MinValue Or temp > Int32.MaxValue Then
Throw New OverflowException(String.Format("{0} is out of range of the Int32 data type.", temp))
End If
Return CInt(Math.Round(temp))
End Function
Public Function ToInt64(provider As IFormatProvider) As Int64 Implements IConvertible.ToInt64
If temp < Int64.MinValue Or temp > Int64.MaxValue Then
Throw New OverflowException(String.Format("{0} is out of range of the Int64 data type.", temp))
End If
Return CLng(Math.Round(temp))
End Function
Public Function ToSByte(provider As IFormatProvider) As SByte Implements IConvertible.ToSByte
If temp < SByte.MinValue Or temp > SByte.MaxValue Then
Throw New OverflowException(String.Format("{0} is out of range of the SByte data type.", temp))
Else
Return CSByte(temp)
End If
End Function
Public Function ToSingle(provider As IFormatProvider) As Single Implements IConvertible.ToSingle
Return CSng(temp)
End Function
Public Overridable Overloads Function ToString(provider As IFormatProvider) As String Implements IConvertible.ToString
Return temp.ToString(provider) & " °C"
End Function
' If conversionType is a implemented by another IConvertible method, call it.
Public Overridable Function ToType(conversionType As Type, provider As IFormatProvider) As Object Implements IConvertible.ToType
Select Case Type.GetTypeCode(conversionType)
Case TypeCode.Boolean
Return Me.ToBoolean(provider)
Case TypeCode.Byte
Return Me.ToByte(provider)
Case TypeCode.Char
Return Me.ToChar(provider)
Case TypeCode.DateTime
Return Me.ToDateTime(provider)
Case TypeCode.Decimal
Return Me.ToDecimal(provider)
Case TypeCode.Double
Return Me.ToDouble(provider)
Case TypeCode.Empty
Throw New NullReferenceException("The target type is null.")
Case TypeCode.Int16
Return Me.ToInt16(provider)
Case TypeCode.Int32
Return Me.ToInt32(provider)
Case TypeCode.Int64
Return Me.ToInt64(provider)
Case TypeCode.Object
' Leave conversion of non-base types to derived classes.
Throw New InvalidCastException(String.Format("Cannot convert from Temperature to {0}.", _
conversionType.Name))
Case TypeCode.SByte
Return Me.ToSByte(provider)
Case TypeCode.Single
Return Me.ToSingle(provider)
Case TypeCode.String
Return Me.ToString(provider)
Case TypeCode.UInt16
Return Me.ToUInt16(provider)
Case TypeCode.UInt32
Return Me.ToUInt32(provider)
Case TypeCode.UInt64
Return Me.ToUInt64(provider)
Case Else
Throw New InvalidCastException("Conversion not supported.")
End Select
End Function
Public Function ToUInt16(provider As IFormatProvider) As UInt16 Implements IConvertible.ToUInt16
If temp < UInt16.MinValue Or temp > UInt16.MaxValue Then
Throw New OverflowException(String.Format("{0} is out of range of the UInt16 data type.", temp))
End If
Return CUShort(Math.Round(temp))
End Function
Public Function ToUInt32(provider As IFormatProvider) As UInt32 Implements IConvertible.ToUInt32
If temp < UInt32.MinValue Or temp > UInt32.MaxValue Then
Throw New OverflowException(String.Format("{0} is out of range of the UInt32 data type.", temp))
End If
Return CUInt(Math.Round(temp))
End Function
Public Function ToUInt64(provider As IFormatProvider) As UInt64 Implements IConvertible.ToUInt64
If temp < UInt64.MinValue Or temp > UInt64.MaxValue Then
Throw New OverflowException(String.Format("{0} is out of range of the UInt64 data type.", temp))
End If
Return CULng(Math.Round(temp))
End Function
End Class
Public Class TemperatureCelsius : Inherits Temperature : Implements IConvertible
Public Sub New(value As Decimal)
MyBase.New(value)
End Sub
' Override ToString methods.
Public Overrides Function ToString() As String
Return Me.ToString(Nothing)
End Function
Public Overrides Function ToString(provider As IFormatProvider ) As String
Return temp.ToString(provider) + "°C"
End Function
' If conversionType is a implemented by another IConvertible method, call it.
Public Overrides Function ToType(conversionType As Type, provider As IFormatProvider) As Object
' For non-objects, call base method.
If Type.GetTypeCode(conversionType) <> TypeCode.Object Then
Return MyBase.ToType(conversionType, provider)
Else
If conversionType.Equals(GetType(TemperatureCelsius)) Then
Return Me
ElseIf conversionType.Equals(GetType(TemperatureFahrenheit))
Return New TemperatureFahrenheit(CDec(Me.temp * 9 / 5 + 32))
' Unspecified object type: throw an InvalidCastException.
Else
Throw New InvalidCastException(String.Format("Cannot convert from Temperature to {0}.", _
conversionType.Name))
End If
End If
End Function
End Class
Public Class TemperatureFahrenheit : Inherits Temperature : Implements IConvertible
Public Sub New(value As Decimal)
MyBase.New(value)
End Sub
' Override ToString methods.
Public Overrides Function ToString() As String
Return Me.ToString(Nothing)
End Function
Public Overrides Function ToString(provider As IFormatProvider ) As String
Return temp.ToString(provider) + "°F"
End Function
Public Overrides Function ToType(conversionType As Type, provider As IFormatProvider) As Object
' For non-objects, call base methood.
If Type.GetTypeCode(conversionType) <> TypeCode.Object Then
Return MyBase.ToType(conversionType, provider)
Else
' Handle conversion between derived classes.
If conversionType.Equals(GetType(TemperatureFahrenheit)) Then
Return Me
ElseIf conversionType.Equals(GetType(TemperatureCelsius))
Return New TemperatureCelsius(CDec((MyBase.temp - 32) * 5 / 9))
' Unspecified object type: throw an InvalidCastException.
Else
Throw New InvalidCastException(String.Format("Cannot convert from Temperature to {0}.", _
conversionType.Name))
End If
End If
End Function
End Class
下面的示例演示对这些 IConvertible 实现的多个调用,以实现 TemperatureCelsius
对象和 TemperatureFahrenheit
对象之间的相互转换。
TemperatureCelsius tempC1 = new TemperatureCelsius(0);
TemperatureFahrenheit tempF1 = (TemperatureFahrenheit) Convert.ChangeType(tempC1, typeof(TemperatureFahrenheit), null);
Console.WriteLine("{0} equals {1}.", tempC1, tempF1);
TemperatureCelsius tempC2 = (TemperatureCelsius) Convert.ChangeType(tempC1, typeof(TemperatureCelsius), null);
Console.WriteLine("{0} equals {1}.", tempC1, tempC2);
TemperatureFahrenheit tempF2 = new TemperatureFahrenheit(212);
TemperatureCelsius tempC3 = (TemperatureCelsius) Convert.ChangeType(tempF2, typeof(TemperatureCelsius), null);
Console.WriteLine("{0} equals {1}.", tempF2, tempC3);
TemperatureFahrenheit tempF3 = (TemperatureFahrenheit) Convert.ChangeType(tempF2, typeof(TemperatureFahrenheit), null);
Console.WriteLine("{0} equals {1}.", tempF2, tempF3);
// The example displays the following output:
// 0°C equals 32°F.
// 0°C equals 0°C.
// 212°F equals 100°C.
// 212°F equals 212°F.
Dim tempC1 As New TemperatureCelsius(0)
Dim tempF1 As TemperatureFahrenheit = CType(Convert.ChangeType(tempC1, GetType(TemperatureFahrenheit), Nothing), TemperatureFahrenheit)
Console.WriteLine("{0} equals {1}.", tempC1, tempF1)
Dim tempC2 As TemperatureCelsius = CType(Convert.ChangeType(tempC1, GetType(TemperatureCelsius), Nothing), TemperatureCelsius)
Console.WriteLine("{0} equals {1}.", tempC1, tempC2)
Dim tempF2 As New TemperatureFahrenheit(212)
Dim tempC3 As TEmperatureCelsius = CType(Convert.ChangeType(tempF2, GEtType(TemperatureCelsius), Nothing), TemperatureCelsius)
Console.WriteLine("{0} equals {1}.", tempF2, tempC3)
Dim tempF3 As TemperatureFahrenheit = CType(Convert.ChangeType(tempF2, GetType(TemperatureFahrenheit), Nothing), TemperatureFahrenheit)
Console.WriteLine("{0} equals {1}.", tempF2, tempF3)
' The example displays the following output:
' 0°C equals 32°F.
' 0°C equals 0°C.
' 212°F equals 100°C.
' 212°F equals 212°F.
TypeConverter 类
.NET Framework 还允许您通过下面的方法为自定义类型定义类型转换器:扩展 System.ComponentModel.TypeConverter 类,然后通过 System.ComponentModel.TypeConverterAttribute 特性将类型转换器与该类型关联。 下表列出了此方法与为自定义类型实现 IConvertible 接口之间的差异。
备注
只能为已定义了类型转换器的自定义类型提供设计时支持。
使用 TypeConverter 转换 | 使用 IConvertible 转换 |
---|---|
通过从 TypeConverter 派生单独的类来为自定义类型实现。 此派生类通过应用 TypeConverterAttribute 特性与自定义类型关联。 | 由自定义类型实现,以执行转换。 该类型的用户必须对该类型调用 IConvertible 转换方法。 |
在设计时和运行时都可以使用。 | 只能在运行时使用。 |
使用反射;因此,比 IConvertible 所启用的转换慢。 | 不使用反射。 |
允许自定义类型和其他数据类型间的双向类型转换。 例如,为 TypeConverter 定义的 MyType 允许从 MyType 转换为 String 以及从 String 转换为 MyType 。 | 允许从自定义类型转换为其他数据类型,但不允许从其他数据类型转换为自定义类型。 |
有关使用类型转换器执行转换的更多信息,请参见 System.ComponentModel.TypeConverter 。
另请参阅
System.Convert
IConvertible
类型转换表
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论