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的东东!)

  • 相关阅读:
    微软推送Win10致全球网络负担增大,中国网友表示毫无压力
    hdu4336Card Collector 概率dp+状态压缩
    利用JAVA反射机制实现调用私有方法
    【D3 API 中文手冊】
    Android线程池(二)——ThreadPoolExecutor及其拒绝策略RejectedExecutionHandler使用演示样例
    输入3个整数,按由小到大的顺序输出(使用指针)
    【直接拿来用のandroid公共代码模块解析与分享】の Notification和NotificationManager
    HDU 1533 Going Home(KM完美匹配)
    项目期复习:JS操作符,弹窗与调试,凝视,数据类型转换
    Oracle11gR2 Windows 7 64bit and PL/SQL Developer排错
  • 原文地址:https://www.cnblogs.com/ServiceboyNew/p/2534630.html
Copyright © 2011-2022 走看看