热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

9.4.2.2F#中的向上转换和向下转换(UPCASTSANDDOWNCASTS)

9.4.2.2F#中的向上转换和向下转换(UPCASTSANDDOWNCASTS)如果类型之间的转换不会失败,就称为向上转换(upcast)。我们已经看到,把类型转换成由该类型实

9.4.2.2 F# 中的向上转换和向下转换(UPCASTSAND DOWNCASTS)

 

如果类型之间的转换不会失败,就称为向上转换(upcast)。我们已经看到,把类型转换成由该类型实现的接口,就是这种情况;另一个示例是把派生类转换成它的基类,在这种情况下,编译器也可以保证操作是正确的,不会失败。

如果有一个基本类型的值,希望将它转换为继承类,操作可能会失败,因为基类的值可能是目标类的值,也可能不是。在这种情况下,我们必须使用第二种类型转换,称为向下转换(downcast)。让我们用一个示例来说明,我们将使用标准的 Random 类,它是从 Object 类派生的(就像任何其他的 .NET 类一样):

 

> open System;; 

> let rnd = new Random();; 

val rnd : Random

 

> let rndObject = (rnd :>Object);;   <-- 成功,操作不会失败

val obj : Object

 

> let rnd2 = (rndObject :>Random);;                     |

stdin(4,12): error: Type constraintmismatch.              | 向上转换不正确

The type 'Object' is not compatible withthe type 'Random'  |

 

> let rnd2 = (rndObject :?>Random);;   <-- 成功,但可能会失败

val rnd2 : Random

 

> (rndObject :?> String);; 

System.InvalidCastException: Unable to castobject of type 

'System.Random' to type 'System.String'.

 

可以发现,如果我们偶然尝试不适当地使用了向上转换,F# 编译器报告这个错误。错误消息说,Object 与 Random 不兼容,这就是说,编译器不能保证 Object  类型的值能够转换到 Random 类型。最后,清单显示,向下转换可能失败,并且,如果试着将对象转换到错误的继承类,会抛出异常。

要想记住 F# 向上转换(>)和向下转换(:?>)的语法,有一个好办法,在使用向下转换时,有一些不确定因素,因为操作可能会失败。这种不确定性是向下转换运算符包含问号,而向上转换不包含的原因。F# 语言还提供了相当于 C# 中 is 的运算符,返回布尔值,说明对象实例是否可以转换为指定的类型。为了测试 obj 是否可以转换为 String,写成 obj :?> String。

在这里,思考一下 F# 和 C# 之间的差异,是值得的。在 C# 中,我们甚至不需要类型转换,如在清单 9.17 中:当编译器知道转换能成功,它不需要消歧,可以让它隐式发生。F# 不进行任何隐式转换,因此,用一个语言结构来表示转换,保证成功,是有道理的。在 C# 中还要使用,就没有什么意义了,所以很少使用,因为两种转换使用相同的语法,更简单。明确指定转换的编程风格,使得类型推断成为可能,而且,通常有助于阐明代码实际上在做什么。 

只用一章(合理的大小!)的篇幅,就想讲清所有F# 面向对象的特性,是不可能的,但我们已经知道要把函数式应用程序转变成实际的 .NET 代码,那些是最重要的。

我们已经多次说过,这些改变使 F# 代码更容易在 C# 中访问,因此,现在是证明的时候了,同时,要展示互操作是如何配合的。

 


推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 本文介绍了Java集合库的使用方法,包括如何方便地重复使用集合以及下溯造型的应用。通过使用集合库,可以方便地取用各种集合,并将其插入到自己的程序中。为了使集合能够重复使用,Java提供了一种通用类型,即Object类型。通过添加指向集合的对象句柄,可以实现对集合的重复使用。然而,由于集合只能容纳Object类型,当向集合中添加对象句柄时,会丢失其身份或标识信息。为了恢复其本来面貌,可以使用下溯造型。本文还介绍了Java 1.2集合库的特点和优势。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 本文详细介绍了使用C#实现Word模版打印的方案。包括添加COM引用、新建Word操作类、开启Word进程、加载模版文件等步骤。通过该方案可以实现C#对Word文档的打印功能。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 测绘程序设计Excel度分秒转换模板附代码超实用版
    本文介绍了测绘程序设计Excel度分秒转换模板附代码超实用版的相关知识,包括准备工作、编写表达式和注意事项。在实际工作中,将GPS实测的经纬度度转换为度分秒是常见需求,本文提供了在Excel中快速进行转换的方法,以提高工作效率。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
author-avatar
xiaobin
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有