当C#比较Nullable<;T>;=null,会发生什么

本文关键字:null 什么 比较 Nullable lt gt | 更新日期: 2023-09-27 18:28:11

当C#将可为null的类型与"null"进行比较时,C#编译器是否首先插入一些代码来检查变量是否有值?

int? fk2=null;
OtherNullable<int> fk3=null;
Console.WriteLine(fk2 == null);
Console.WriteLine(fk3 == null);

在上下文中,我试图弄清楚equality+隐式和显式强制转换应该是什么样子,以便能够比较fk3和null。

假设您按照这里发布的代码实现了Nullable:如何实现Nullable<T>在幕后打字?并称之为OtherNullable<T>

除了val==null在运行时不起作用之外,只需少量修改即可正常工作。

实施:

[Serializable, StructLayout(LayoutKind.Sequential)]
public struct OtherNullable<T> : IEquatable<OtherNullable<T>> where T : struct {
    private bool hasValue;
    internal T value;
    public OtherNullable(T value)
        : this() {
        this.value = value;
        this.hasValue = true;
    }
    public OtherNullable(T? value) {
        this.value = default(T);
        this.hasValue = false;
    }
    public bool HasValue {
        get { return this.hasValue; }
    }
    public T Value {
        get {
            if (!this.HasValue) {
                throw new InvalidOperationException("No Value");
            }
            return this.value;
        }
    }
    public OtherNullable(bool b) {
        this.value = default(T);
        this.hasValue = false;
    }
    public T GetValueOrDefault() {
        return this.value;
    }
    public T GetValueOrDefault(T defaultValue) {
        if (!this.HasValue) {
            return defaultValue;
        }
        return this.value;
    }
    public bool Equals(OtherNullable<T> other)
    {
        if (!other.HasValue & !this.HasValue)
            return true;
        else
            return other.hasValue.Equals(hasValue) && other.value.Equals(value);
    }
    public static bool operator ==(OtherNullable<T> left, OtherNullable<T> right) {
        return left.Equals(right);
    }
    public static bool operator !=(OtherNullable<T> left, OtherNullable<T> right) {
        return !left.Equals(right);
    }
    public override bool Equals(object other) {
        if (ReferenceEquals(null, other)) return false;
        if (other.GetType() != typeof(OtherNullable<T>)) return false;
        return Equals((OtherNullable<T>)other);
    }
    public override int GetHashCode() {
        unchecked {
            return (hasValue.GetHashCode() * 397) ^ value.GetHashCode();
        }
    }
    public override string ToString() {
        if (!this.HasValue) {
            return "";
        }
        return this.value.ToString();
    }
    public static implicit operator OtherNullable<T>(T value) {
        return new OtherNullable<T>(value);
    }
    public static explicit operator T(OtherNullable<T> value) {
        return value.Value;
    }
    public static implicit operator OtherNullable<T>(Nullable<T> value) {
        if (value.HasValue) {
            return new OtherNullable<T>(value.Value);
        } else {
            return new OtherNullable<T>(null);
        }
    }
}

测试代码(不会编译——以前是这样):

[TestFixture]
public class TestOtherNullable {
    [Test]
    public void Test()
    {
        var a = new OtherNullable<int>();
        a = 1;
        Assert.IsTrue(a.HasValue);
        Assert.IsFalse(a == null);
        var b = new OtherNullable<int>();
        b = null;
        Assert.IsTrue(b == null);
    }
}

当C#比较Nullable<;T>;=null,会发生什么

任何Nullable<T>null的相等性检查等价于!nullable.HasValue。它没有其他有意义的语义。我不确定OtherNullable<T>的处理方式,因为它不是标准类型。

Q: ";当C#将可为null的类型与"0"进行比较时;空";,C#编译器先插入一些代码来检查变量是否有值"

A: 编译器不在此实例中插入代码。在这种情况下,Equals运算符被覆盖如下:

public override bool Equals(object other)
{
    if (!this.HasValue)
    {
        return (other == null);
    }
    if (other == null)
    {
        return false;
    }
    return this.value.Equals(other);
}

它确实负责将其与null进行比较。

编译器通过以下方式帮助您:

// this
int? x = null;
// Transformed to this
int? x = new Nullable<int>()
// this
if (x == null) return;
// Transformed to this
if (!x.HasValue) return;
// this
if (x == 2) return;
// Transformed to this
if (x.GetValueOrDefault() == 2 && x.HasValue) return;

所有这些信息都在您链接的问题中。

感谢@barrylloyd和@ChaosPandion