You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中检查对象是否包含默认值(含嵌套对象场景)

检查对象是否为默认初始化实例(含嵌套对象)

你遇到的问题很典型:直接用==或者Object.ReferenceEquals比较对象和新实例,永远会返回false——因为每次new都会创建一个全新的对象引用,这两个方法本质都是在比较引用是否相同,而不是对象的属性值是否一致。

下面分两种场景给你解决方案:

一、简单对象(无嵌套属性)的情况

方案1:重写Equals和GetHashCode

最直接的方式是在你的类中重写Equals方法,手动比较对象的属性值是否和默认实例一致,同时重写GetHashCode保证哈希值匹配:

public class MyClass {
    public int Value { get; set; }
    public MyClass() {
        this.Value = 10;
    }

    // 重写Equals,比较属性值
    public override bool Equals(object obj) {
        // 先判断引用是否相同,或者类型不匹配/为空
        if (obj == null || GetType() != obj.GetType())
            return false;
        
        MyClass other = (MyClass)obj;
        // 比较所有默认初始化的属性
        return Value == other.Value;
    }

    // 重写GetHashCode,确保相等的对象哈希值一致
    public override int GetHashCode() {
        return Value.GetHashCode();
    }
}

之后你就可以这样判断:

if(obj1.Equals(new MyClass()))
    Console.WriteLine("Initialized with default values");

方案2:重载==运算符

如果你习惯用==语法,还可以重载==和!=运算符,让它直接比较属性值:

public class MyClass {
    // ... 保留上面的构造函数、Equals和GetHashCode ...

    public static bool operator ==(MyClass a, MyClass b) {
        // 先处理引用相同的情况
        if (ReferenceEquals(a, b))
            return true;
        // 处理其中一个为空的情况
        if (a is null || b is null)
            return false;
        // 调用Equals比较属性
        return a.Equals(b);
    }

    public static bool operator !=(MyClass a, MyClass b) {
        return !(a == b);
    }
}

现在原来的obj1 == new MyClass()就能正常工作了。

另外,检查对象是否为空直接用obj2 == null就可以,这个是没问题的。

二、包含嵌套对象的场景

如果你的类有嵌套的自定义对象,需要递归比较嵌套对象的属性值,同样可以通过重写Equals实现:

步骤1:给嵌套类重写Equals和GetHashCode

public class MyNestedClass {
    public string SomeStringProperty { get; set; }
    public MyNestedClass() {
        this.SomeStringProperty = "Some string";
    }

    public override bool Equals(object obj) {
        if (obj == null || GetType() != obj.GetType())
            return false;
        
        MyNestedClass other = (MyNestedClass)obj;
        return SomeStringProperty == other.SomeStringProperty;
    }

    public override int GetHashCode() {
        return SomeStringProperty?.GetHashCode() ?? 0;
    }
}

步骤2:在主类的Equals中递归比较嵌套属性

public class MyClass {
    public int Value { get; set; }
    public MyNestedClass MyProperty { get; set; }
    public MyClass() {
        this.Value = 10;
        this.MyProperty = new MyNestedClass();
    }

    public override bool Equals(object obj) {
        if (obj == null || GetType() != obj.GetType())
            return false;
        
        MyClass other = (MyClass)obj;
        // 比较自身属性 + 递归比较嵌套对象
        return Value == other.Value && Equals(MyProperty, other.MyProperty);
    }

    public override int GetHashCode() {
        // 组合自身和嵌套对象的哈希值
        return HashCode.Combine(Value, MyProperty);
    }
}

这样obj1.Equals(new MyClass())就会正确判断所有嵌套属性是否都是默认值了。

通用方案:用反射自动比较所有属性

如果你的项目中有很多类需要做这种检查,手动重写Equals太麻烦,可以写一个通用的反射方法,自动遍历所有属性并比较:

public static bool IsDefaultInstance<T>(T obj) where T : new() {
    if (obj == null)
        return false;
    
    // 创建一个默认实例作为参照
    T defaultInstance = new T();
    // 获取所有公共实例属性
    var properties = typeof(T).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
    
    foreach (var prop in properties) {
        object objValue = prop.GetValue(obj);
        object defaultValue = prop.GetValue(defaultInstance);
        
        // 如果是自定义类(排除string,因为string是值类型语义),递归检查
        if (prop.PropertyType.IsClass && prop.PropertyType != typeof(string)) {
            if (!IsDefaultInstance(objValue))
                return false;
        } 
        // 值类型或string直接比较
        else if (!Equals(objValue, defaultValue)) {
            return false;
        }
    }
    
    return true;
}

使用方式非常简单:

if (IsDefaultInstance(obj1))
    Console.WriteLine("Initialized with default values");

注意:反射会有一定的性能开销,如果是性能敏感的场景(比如高频循环中),还是建议手动重写Equals。

内容的提问来源于stack exchange,提问作者Kunal Mukherjee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:06:20