c# – 是否有技术原因没有从DBNull到可空类型的隐式转换?
是否存在技术原因导致没有从DBNull到各种可空和/或sql类型的隐式转换?我理解为什么转换当前没有发生,但是不明白为什么当时没有创建隐式转换或者在框架的后续版本中添加了隐式转换.
为了清楚起见,我正在寻找技术原因,而不是“因为他们是这样做的”或“我喜欢它”. 解决方法
好吧,我不知道SqlTypes的情况,但肯定有一些技术原因,为什么在DBNull.Value和Nullable< T>的值之间添加隐式转换.使用HasValue = false将无法正常工作.
记住,DBNull是一种引用类型,尽管Nullable< T>像一个引用类型 – 假装能够采用空值 – 它实际上是一个值类型,具有值语义. 特别是,当类型为Nullable< T>的值时,存在一种奇怪的边缘情况.盒装.该行为在运行时特殊情况下为Nullable< T>类型的框值.到盒装版本的T,而不是Nullable< T>的盒装版本. 正如the MSDN documentation解释的那样:
现在我们遇到了一个棘手的问题:C#语言规范(§4.3.2)说我们不能使用拆箱转换将DBNull.Value转换为Nullable< T>:
根据§10.10.3,我们也不能使用用户定义的转换从对象转换为Nullable< T>
好的,你或我做不到,但微软可以修改规范,并使其合法,对吧?我不这么认为. 为什么?好吧,想象一下预期的用例:你有一些指定返回对象的方法.实际上,它要么返回DBNull.Value,要么返回int.但编译器怎么知道呢?它只知道该方法被指定为返回对象.并且必须在编译时选择要应用的转换运算符. 好吧,假设有一些神奇的运算符可以从对象转换为Nullable< T>,并且编译器有一些方法可以知道它何时适用. (我们不希望它用于指定返回对象的每个方法 – 如果方法实际返回一个字符串,它应该怎么做?)但是我们仍然有一个问题:转换可能不明确!如果方法返回long或DBNull.Value,我们做int? v = Method();,当方法返回一个盒装长的时候我们应该怎么做? 基本上,为了使其按预期工作,您必须使用等效的dynamic来确定运行时的类型并根据运行时类型进行转换.但后来我们又打破了另一条规则:由于实际转换只能在运行时选择,因此无法保证它实际上会成功.但隐式转换不应该抛出异常. 所以在这一点上,它不仅是对语言的指定行为的改变,一个潜在的重大性能打击,而且它可能会引发意外的异常!这似乎是不实施它的一个很好的理由.但如果您还需要一个理由,请记住每个功能都从minus 100 points开始. 简而言之:无论如何,你真正想要的是隐式转换.如果你想要动态的行为,只需使用动态!这样做你想要的,并已在C#4.0中实现: object x = 23; object y = null; dynamic dx = x; dynamic dy = y; int? nx = (int?) dx; int? ny = (int?) dy; Console.WriteLine("nx.HasValue = {0}; nx.Value = {1}; ny.HasValue = {2};",nx.HasValue,nx.Value,ny.HasValue); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- PostgreSQL 创建分区表,SQL优化之PostgreSQL Table Partit
- C++编程中私有和保护以及公有的类成员访问控制
- 使用XCTest设置一个带有两个测试目标的TestProject,用于iOS
- oracle教程:PLSQL常用方法汇总
- ruby-on-rails – 如何创建多种类型的has_many关联?
- Swift 的nil
- 可可触摸 – 在swift中获取类名的用户可读版本(在objc NSSt
- ruby-on-rails – 没有外键的ActiveRecord关联
- postgresql – postgres中的@>运算符有什么作用?
- objective-c – ios programming – 格式字符串不使用的数据