加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 是否有技术原因没有从DBNull到可空类型的隐式转换?

发布时间:2020-12-15 04:29:49 所属栏目:百科 来源:网络整理
导读:是否存在技术原因导致没有从DBNull到各种可空和/或sql类型的隐式转换?我理解为什么转换当前没有发生,但是不明白为什么当时没有创建隐式转换或者在框架的后续版本中添加了隐式转换. 为了清楚起见,我正在寻找技术原因,而不是“因为他们是这样做的”或“我喜欢
是否存在技术原因导致没有从DBNull到各种可空和/或sql类型的隐式转换?我理解为什么转换当前没有发生,但是不明白为什么当时没有创建隐式转换或者在框架的后续版本中添加了隐式转换.

为了清楚起见,我正在寻找技术原因,而不是“因为他们是这样做的”或“我喜欢它”.

解决方法

好吧,我不知道SqlTypes的情况,但肯定有一些技术原因,为什么在DBNull.Value和Nullable< T>的值之间添加隐式转换.使用HasValue = false将无法正常工作.

记住,DBNull是一种引用类型,尽管Nullable< T>像一个引用类型 – 假装能够采用空值 – 它实际上是一个值类型,具有值语义.

特别是,当类型为Nullable< T>的值时,存在一种奇怪的边缘情况.盒装.该行为在运行时特殊情况下为Nullable< T>类型的框值.到盒装版本的T,而不是Nullable< T>的盒装版本.

正如the MSDN documentation解释的那样:

When a nullable type is boxed,the common language runtime automatically boxes the underlying value of the Nullable(Of T) object,not the Nullable(Of T) object itself. That is,if the HasValue property is true,the contents of the Value property is boxed. When the underlying value of a nullable type is unboxed,the common language runtime creates a new Nullable(Of T) structure initialized to the underlying value.

If the HasValue property of a nullable type is false,the result of a boxing operation is Nothing. Consequently,if a boxed nullable type is passed to a method that expects an object argument,that method must be prepared to handle the case where the argument is Nothing. When Nothing is unboxed into a nullable type,the common language runtime creates a new Nullable(Of T) structure and initializes its HasValue property to false.

现在我们遇到了一个棘手的问题:C#语言规范(§4.3.2)说我们不能使用拆箱转换将DBNull.Value转换为Nullable< T>:

For an unboxing conversion to a given nullable-type to succeed at run-time,the value of the source operand must be either null or a reference to a boxed value of the underlying non-nullable-value-type of the nullable-type. If the source operand is a reference to an incompatible object,a System.InvalidCastException is thrown.

根据§10.10.3,我们也不能使用用户定义的转换从对象转换为Nullable< T>

It is not possible to directly redefine a pre-defined conversion. Thus,conversion operators are not allowed to convert from or to object because implicit and explicit conversions already exist between object and all other types.

好的,你或我做不到,但微软可以修改规范,并使其合法,对吧?我不这么认为.

为什么?好吧,想象一下预期的用例:你有一些指定返回对象的方法.实际上,它要么返回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);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读