当C#比较Nullable <t> == null时,会发生什么?</t>

时间:2012-03-19 12:34:12

标签: c#

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

int? fk2=null;
OtherNullable<int> fk3=null;

Console.WriteLine(fk2 == null);

Console.WriteLine(fk3 == null);

上下文,我正在尝试找出相等+隐式和显式转换应该是什么样子来启用fk3和null的比较。

假设您根据此处发布的代码实施了Nullable:How does a Nullable<T> type work behind the scenes?并将其称为OtherNullable<T>

除了v​​al == 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);
    }
}

2 个答案:

答案 0 :(得分:6)

任何Nullable<T>null的等同检查等效!nullable.HasValue。它没有其他语义可行。我不确定与OtherNullable<T>的交易是什么,因为那不是标准类型。

答案 1 :(得分:2)

问:“当C#将可空类型与”null“进行比较时,C#编译器是否会插入一些代码来检查变量是否首先具有值?”

答:编译器不会在此实例中插入代码。在这种情况下,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;

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

感谢@barrylloyd和@ChaosPandion