C#自定义泛型结构,具有与Nullable <t>相同的编译器行为

时间:2017-05-05 14:01:32

标签: c# .net

在C#中使用System.Nullable<T>观看以下示例。

int x = 5;
int? y = 3;
int? result = x + y; //no compiler warning

编译器可以判断Tint是有意义的,因此它可以使用运算符。

也在
int x = 5;
int? y = 3;
bool result = x == y; //no compiler warning

有意义的是,如果xnull,则表达式为false。编译器并不介意。

现在我正在尝试创建一个类似于Nullable<T>的课程。我们称之为Lookable<T>

[Serializable]
public struct Lookable<T> where T : struct
{
    public Lookable(T value)
    {
        Value = value;
    }

    public T Value { get; }

    public override bool Equals(object other)
    {
        return other != null && Value.Equals(other);
    }

    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }

    public override string ToString()
    {
        return Value.ToString();
    }

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

    public static explicit operator T(Lookable<T> value)
    {
        return value.Value;
    }
}

这里的想法直接来自.NET's source code。在我的情况下,我只是省略HasValue属性。 现在这个例子可行:

int x = 6;
Lookable<int> y = x;
Lookable<int> z = 4;

编译器可以在此推断出类型,因为implicit operator正确吗?
我不明白的是,这个例子会让编译器不高兴:

int x = 5;
Lookable<int> y = 3;
var result1 = x + y; //compile error
var result2 = x == y; //compile error

编译器给我的信息是:

  

运算符无法应用于&#39; int&#39;类型的操作数。和&#39; Lookable<int>&#39;。

为什么不呢?为什么Nullable<T>可以实现?我无法在源代码中找到它。是Lookable<T>还是可能吗?

1 个答案:

答案 0 :(得分:5)

这个代码不在Nullable<T>中 - 它在C#编译器中,特别是规范中的“提升操作符”,以及它们如何将特别应用于{{1 }}。规范参考在this answer

您无法在自己的类型中重现System.Nullable<T>行为。它由编译器和运行时(装箱等)进行特殊处理。