Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可为空<;T>;实施_C#_.net_Nullable - Fatal编程技术网

C# 可为空<;T>;实施

C# 可为空<;T>;实施,c#,.net,nullable,C#,.net,Nullable,我正在尝试实现可为null的类型。但下面提到的代码不支持valuetype数据类型的null值 using System; using System.Runtime; using System.Runtime.InteropServices; namespace Nullable { [Serializable, StructLayout(LayoutKind.Sequential)] public struct Nullable<T> where T :

我正在尝试实现可为null的类型。但下面提到的代码不支持valuetype数据类型的null值

using System;
using System.Runtime;
using System.Runtime.InteropServices;

namespace Nullable
{

    [Serializable, StructLayout(LayoutKind.Sequential)]    
    public struct Nullable<T> where T : struct
    {
        private bool hasValue;

        public bool HasValue
        {
            get { return hasValue; }
        }

        internal T value;

        public Nullable(T value)
        {
            this.value = value;
            this.hasValue = true;
        }

        public T Value
        {
            get
            {
                if (!this.hasValue)
                {
                    new InvalidOperationException("No value assigned");
                }
                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 obj)
        {
            if (!this.HasValue)
            {
                return obj == null;
            }
            if (obj == null)
            {
                return false;
            }
            return this.value.Equals(obj);
        }

        public override int GetHashCode()
        {
            if (!this.hasValue)
            {
                return 0;
            }
            return this.value.GetHashCode();
        }

        public override string ToString()
        {
            if (!this.hasValue)
            {
                return string.Empty;
            }
            return this.value.ToString();
        }

        public static implicit operator Nullable<T>(T value)
        {
            return new Nullable<T>(value);
        }

        public static explicit operator T(Nullable<T> value)
        {
            return value.Value;
        }
    }
}
使用系统;
使用系统运行时;
使用System.Runtime.InteropServices;
命名空间可为空
{
[可序列化,StructLayout(LayoutKind.Sequential)]
公共结构为null,其中T:struct
{
私有布尔值;
公共布尔值
{
获取{return hasValue;}
}
内部T值;
公共可为空(T值)
{
这个值=值;
this.hasValue=true;
}
公共价值
{
得到
{
如果(!this.hasValue)
{
新的无效操作异常(“未分配值”);
}
返回此.value;
}
}
公共T GetValuerDefault()
{
返回此.value;
}
公共T获取值默认值(T默认值)
{
如果(!this.HasValue)
{
返回默认值;
}
返回此.value;
}
公共覆盖布尔等于(对象对象对象)
{
如果(!this.HasValue)
{
返回obj==null;
}
if(obj==null)
{
返回false;
}
返回此.value.Equals(obj);
}
公共覆盖int GetHashCode()
{
如果(!this.hasValue)
{
返回0;
}
返回此.value.GetHashCode();
}
公共重写字符串ToString()
{
如果(!this.hasValue)
{
返回字符串。空;
}
返回此.value.ToString();
}
公共静态隐式运算符可为null(T值)
{
返回新的可为空(值);
}
公共静态显式运算符T(可空值)
{
返回值;
}
}
}
当我试图将该值赋值为null时,它抛出了一个错误“无法将null转换为'Nullable.Nullable',因为它是不可为null的值类型”


要解决这个问题,我必须做什么?

null
赋值给
Nullable
只是赋值
new Nullable()
的一种语法糖,它是C语言的一部分,您不能将该功能添加到自定义类型中

C#规格

4.1.10可空类型

可为null的类型可以表示其基础类型的所有值 一个附加的空值。可为空的类型写为T?,其中T为 基础类型。此语法是System.Nullable的缩写, 这两种形式可以互换使用

6.1.5空文字转换

存在从空文本到任何可空文本的隐式转换 类型。此转换产生给定值的空值(§4.1.10) 可空类型

你不能这样做。

这是一个特例。它在CLR级别上有特殊的处理(这不是纯C语言的功能-特别是,CLR支持装箱/取消装箱空值的特殊场景)。

您将自己生成的空值声明为
结构,而
结构不可空值。
您应该将其声明为

此代码应抛出与您所遇到的错误相同的错误, 将点类型声明从
struct
切换到
class
应该可以解决这个问题

void Main()
{
    Point p = null;
}

// Define other methods and classes here
struct Point
{
 public int X   {get; set;}
 public int Y   {get; set;}
}

为什么要重新发明控制盘?由于以下几个原因,不可能创建一个具有与.NET类型相同功能的
null
类型。这只是其中之一。我只是想了解它们是如何在Framework中实现的。我很确定编译器和运行时有一些“特殊情况”实现专门针对系统提供的可空类型来处理这一问题,您不能自己重新实现它们。下面是一些您可以注意的内容