zoukankan      html  css  js  c++  java
  • 有趣的“Nullable”

    众所周知,Nullable是允许对一些值类型的数据类型直接赋值Null(VB.NET中为Nothing)的特殊值类型。如果你反编译这个值类型,将会看到这样一个局面——

    [C#]

    public struct Nullable<T> where T: struct
    {
        private bool hasValue;
        internal T value;
        public Nullable(T value)
        {
            this.value = value;
            this.hasValue = true;
        }
    
        public bool HasValue
        {
            get
            {
                return this.hasValue;
            }
        }
        public T Value
        {
            get
            {
                if (!this.HasValue)
                {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
                }
                return this.value;
            }
        }
        public T GetValueOrDefault()
        {
            return this.value;
        }
    
        public T GetValueOrDefault(T defaultValue)
        {
            if (!this.HasValue)
            {
                return defaultValue;
            }
            return this.value;
        }
    
        public override bool Equals(object other)
        {
            if (!this.HasValue)
            {
                return (other == null);
            }
            if (other == null)
            {
                return false;
            }
            return this.value.Equals(other);
        }
    
        public override int GetHashCode()
        {
            if (!this.HasValue)
            {
                return 0;
            }
            return this.value.GetHashCode();
        }
    
        public override string ToString()
        {
            if (!this.HasValue)
            {
                return "";
            }
            return this.value.ToString();
        }
    
        public static implicit operator T?(T value)
        {
            return new T?(value);
        }
    
        public static explicit operator T(T? value)
        {
            return value.Value;
        }
    }

    [VB.NET]

    <Serializable, StructLayout(LayoutKind.Sequential), TypeDependency("System.Collections.Generic.NullableEqualityComparer`1"), TypeDependency("System.Collections.Generic.NullableComparer`1")> _
    Public Structure Nullable(Of T As Structure)
        Private hasValue As Boolean
        Friend value As T
        Public Sub New(ByVal value As T)
            Me.value = value
            Me.hasValue = True
        End Sub
    
        Public ReadOnly Property HasValue As Boolean
            Get
                Return Me.hasValue
            End Get
        End Property
    
        Public ReadOnly Property Value As T
            Get
                If Not Me.HasValue Then
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue)
                End If
                Return Me.value
            End Get
        End Property
    
        Public Function GetValueOrDefault() As T
            Return Me.value
        End Function
    
        Public Function GetValueOrDefault(ByVal defaultValue As T) As T
            If Not Me.HasValue Then
                Return defaultValue
            End If
            Return Me.value
        End Function
    
        Public Overrides Function Equals(ByVal other As Object) As Boolean
            If Not Me.HasValue Then
                Return (other Is Nothing)
            End If
            If (other Is Nothing) Then
                Return False
            End If
            Return Me.value.Equals(other)
        End Function
    
        Public Overrides Function GetHashCode() As Integer
            If Not Me.HasValue Then
                Return 0
            End If
            Return Me.value.GetHashCode
        End Function
    
        Public Overrides Function ToString() As String
            If Not Me.HasValue Then
                Return ""
            End If
            Return Me.value.ToString
        End Function
    
        Public Shared Widening Operator CType(ByVal value As T) As T?
            Return New T?(value)
        End Operator
    
        Public Shared Narrowing Operator CType(ByVal value As T?) As T
            Return value.Value
        End Operator
    End Structure

    以上是Nullable提供的不同种类的方法(包含初始化构造函数,强制类型转换等)。不过有一个有趣的问题——

    设想一下把null赋值给Nullable<int>,那么应该系统会调用(C#中,implicit;VB.NET中Widening)那个方法,生成一个新的T类型并传入value。现在问题在于——如果Nullable的泛型类型指定是int,那么对应构造函数的T也是int,你怎么把null赋值给int了呢?

    在VB.NET中因为对任意一个值类型赋值Nothing,其实就是初始化这些变量,所以VB.NET很好理解;C#呢?C#是不允许把null赋值给一个值类型的呀!怎么办呢?微软“别出心裁”地在编译时做了手脚(CLR小动作哦!)——注意看,当你在C#中写了:

    int? n = null;

    其实编译器会将其编译为:

    Nullable<int> n = new Nullable<int>();

    通过调用默认构造函数来初始化这个int(也就是说——Nullable内部的那个value还是0,只不过HasValue标识默认设置为false,何况微软重写了ToString方法,导致该类型“可空”,说白了根本没有“可空”这回事情,也根本不存在“值类型”=null的东东!)

  • 相关阅读:
    windows命令提示符常用命令
    JAVA中定义不同进制整数
    进制转换
    win10配置jdk环境变量
    AI Gossip
    搜狗大数据总监、Polarr 联合创始人关于深度学习的分享交流 | 架构师小组交流会
    后端渲染实践——看掘金社区是如何实践的
    谢孟军:The State of Go | ECUG Con 精粹系列
    让你的 CDN 费用省 50% 以上!图片瘦身的正确姿势
    七牛云大数据平台建设实践
  • 原文地址:https://www.cnblogs.com/ServiceboyNew/p/2534630.html
Copyright © 2011-2022 走看看