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

如何为Cell类实现支持可空泛型类型的显式转换静态方法?

问题描述

现有Cell类定义

public class Cell
{
    readonly private string? _rawString;

    public Cell(string inpString)
    {
        this._rawString = inpString == "" ? null : inpString;
    }

    public static explicit operator DateTime(Cell cell)
    {
        DateTime date = DateTime.MinValue;
        if (DateTime.TryParseExact(cell._rawString, "yyyy/MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
        {
            return date;
        }

        else
        {
            throw new InvalidCastException($"Cannot convert {cell._rawString} to a date.");
        }
    }

    public static explicit operator DateTime?(Cell cell)
    {
        return cell._rawString is null ? null : (DateTime)cell;
    }

    public static explicit operator string(Cell cell)
    {
        return cell._rawString;
    }
}

需求

希望实现一个静态方法ConvertType<T>,支持如下调用:

string? stringFormat = Cell.ConvertType<string?>(cell);
DateTime? dateFormat = Cell.ConvertType<DateTime?>(cell);

尝试的代码及问题

尝试了以下方法,但无法处理可空泛型类型:

public static T TryConvert<T>(Cell cell)
{
    if (cell._rawString is null && typeof(T).IsClass) return default(T);
    if (typeof(T) == typeof(DateTime)) return (T)(object)(DateTime)cell;
    if (typeof(T) == typeof(Decimal)) return (T)(object)(Decimal)cell;
    if (typeof(T) == typeof(int)) return (T)(object)(int)cell;
    if (typeof(T) == typeof(string)) return (T)(object)(string)cell;
    // Add more cases for other types as needed
    throw new InvalidCastException($"Cannot convert {cell._rawString} to {typeof(T)}.");
}
解决方案

要支持可空泛型类型,核心是识别并处理可空值类型的基础类型,同时兼容引用类型的可空场景。修改后的代码如下:

public static T ConvertType<T>(Cell cell)
{
    // 处理原始字符串为null的场景
    if (cell._rawString is null)
    {
        // 可空类型或引用类型直接返回null对应的默认值
        if (typeof(T).IsNullableType())
        {
            return default(T);
        }
        // 非可空值类型无法转换null,抛出异常
        throw new InvalidCastException($"Cannot convert null to non-nullable type {typeof(T)}.");
    }

    // 提取实际转换目标类型:如果是可空值类型,取其基础类型
    Type targetType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);

    // 执行类型转换
    object convertedValue = targetType.Name switch
    {
        nameof(DateTime) => (DateTime)cell,
        nameof(decimal) => decimal.Parse(cell._rawString), // 可根据需求替换为TryParse逻辑
        nameof(int) => int.Parse(cell._rawString), // 可根据需求替换为TryParse逻辑
        nameof(string) => cell._rawString,
        // 扩展其他需要支持的类型
        _ => throw new InvalidCastException($"Cannot convert {cell._rawString} to {typeof(T)}.")
    };

    // 转换回泛型T并返回
    return (T)convertedValue;
}

// 扩展方法:判断类型是否为可空类型(包括可空值类型和引用类型)
private static bool IsNullableType(this Type type)
{
    if (!type.IsValueType) return true; // 引用类型天然可空
    return Nullable.GetUnderlyingType(type) != null; // 值类型判断是否为Nullable<T>
}

关键修改说明

  • null场景处理:针对_rawString为null的情况,区分可空/非可空类型返回对应结果或抛出异常。
  • 可空类型解析:通过Nullable.GetUnderlyingType提取可空值类型的基础类型,统一复用非可空类型的转换逻辑。
  • 辅助判断方法:新增IsNullableType扩展方法,简化可空类型的判断逻辑。
  • 结构化匹配:用switch表达式替代多if判断,代码更简洁易维护。

调用示例

Cell nullCell = new Cell("");
Cell dateCell = new Cell("2024/05/20");
Cell stringCell = new Cell("Hello");
Cell intCell = new Cell("123");

string? strResult = Cell.ConvertType<string?>(nullCell); // 返回null
DateTime? dateResult = Cell.ConvertType<DateTime?>(dateCell); // 返回2024-05-20
int? intResult = Cell.ConvertType<int?>(intCell); // 返回123

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 10:25:23