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

如何获取使用自定义结构体的类属性名称以优化异常信息?

如何让NonNullableString抛出的异常包含属性名称

我定义了一个NonNullableString结构体,通过隐式转换实现字符串非空校验,避免在类构造函数中重复编写空值检查逻辑,但当传入null时,抛出的ArgumentNullException无法指明具体是哪个属性(比如User类的Username)导致的问题,异常信息仅显示value参数,不利于排查定位。


现有NonNullableString结构体代码

public struct NonNullableString
{
    public string Value { get; set; }

    private NonNullableString(string value)
    {
        if (value == null)
            throw new ArgumentNullException($"{value} cannot be null!", nameof(value));

        Value = value;
    }

    public static implicit operator NonNullableString(string value)
    {
        return new NonNullableString(value);
    }

    public static implicit operator string(NonNullableString value)
    {
        return value.Value;
    }
}

使用示例(User类)

public class User
{
    public NonNullableString Username { get; set; }

    // ... 其他属性
    
    public User(string username)
    {
        Username = username;    
    }
}

当前问题

调用new User(null)时,抛出的异常信息为:

Unhandled exception. System.ArgumentNullException: value (Parameter ' cannot be null!')

无法得知是Username属性导致的空值问题,不利于异常排查和日志记录。


解决方案

方案1:使用CallerMemberName特性自动获取属性名

通过[CallerMemberName]特性,让构造函数自动捕获调用方的属性名称,无需手动传递,同时将Value设为只读避免后续被篡改。

修改后的结构体代码:

using System.Runtime.CompilerServices;

public struct NonNullableString
{
    public string Value { get; } // 改为只读,防止实例创建后被设为null

    private NonNullableString(string value, [CallerMemberName] string propertyName = "")
    {
        if (value == null)
            throw new ArgumentNullException(propertyName, $"属性 {propertyName} 不能为空!");

        Value = value;
    }

    public static implicit operator NonNullableString(string value)
    {
        return new NonNullableString(value);
    }

    public static implicit operator string(NonNullableString value)
    {
        return value.Value;
    }
}

此时调用new User(null)会抛出明确指向属性的异常:

Unhandled exception. System.ArgumentNullException: Username (属性 Username 不能为空!)

方案2:显式传递属性名(适合自定义场景)

如果需要对特定属性做自定义异常处理,可以在类的属性setter中显式传递属性名,这种方式灵活性更高,但会失去隐式转换的简洁性:

public class User
{
    private NonNullableString _username;
    public NonNullableString Username
    {
        get => _username;
        set => _username = new NonNullableString(value.Value, nameof(Username));
    }

    public User(string username)
    {
        Username = username;    
    }
}

补充说明

启用Nullable引用类型后,编译器会对可能为null的字符串赋值发出警告,但不会阻止运行时传入null。NonNullableString结构体可以在运行时强制校验,同时配合编译器警告提前发现潜在问题。

内容的提问来源于stack exchange,提问作者Melih Çoban

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:27:02