使用模板化类型的 C# 模式匹配

标签 c# switch-statement

如何使用模式匹配开关重写此方法?

internal ResultType Fetch<ResultType>(string field)
{
    var type = typeof(ResultType);
    object xx = type switch
    {
        _ when type == typeof(DateTime) => FetchDateTime(field),
        _ when type == typeof(DateOnly) => FetchDateOnly(field),
        _ when type == typeof(bool) => FetchBool(field),
        _ when type == typeof(decimal) => FetchDecimal(field),
        _ when type == typeof(string) => FetchString(field),
        _ when type == typeof(int) => FetchInt(field),

        _ => throw new NotImplementedException($"this[field: {field}]")
    };

    if (xx is ResultType rt) return rt;
    return default(ResultType)!;
}

最佳答案

作为答案发布,因为代码太长,无法发表评论。

您当然可以提高效率(忽略长度方面)。 JIT 识别模式 if (type == typeof(DateTime)) 等,并将发出仅保留给定 ResultType 方法的相关部分的代码。

例如,当 ResultTypeDateTime 时,您的代码会产生以下结果:

C.Fetch[[System.DateTime, System.Private.CoreLib]](System.String)
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: push esi
    L0004: sub esp, 8
    L0007: mov esi, edx
    L0009: mov ecx, 0x6e099a4
    L000e: call 0x060a300c
    L0013: lea edx, [eax+4]
    L0016: xor ecx, ecx
    L0018: mov [edx], ecx
    L001a: mov [edx+4], ecx
    L001d: mov edx, eax
    L001f: test edx, edx
    L0021: je short L002b
    L0023: cmp dword ptr [edx], 0x6e099a4
    L0029: je short L003a
    L002b: xor eax, eax
    L002d: mov [esi], eax
    L002f: mov [esi+4], eax
    L0032: lea esp, [ebp-4]
    L0035: pop esi
    L0036: pop ebp
    L0037: ret 4
    L003a: add eax, 4
    L003d: mov edx, [eax]
    L003f: mov eax, [eax+4]
    L0042: mov [ebp-0xc], edx
    L0045: mov [ebp-8], eax
    L0048: mov eax, esi
    L004a: mov edx, [ebp-0xc]
    L004d: mov [eax], edx
    L004f: mov edx, [ebp-8]
    L0052: mov [eax+4], edx
    L0055: lea esp, [ebp-4]
    L0058: pop esi
    L0059: pop ebp
    L005a: ret 4

但是代码:

internal ResultType Fetch2<ResultType>(string field)
{
    var type = typeof(ResultType);
    if (type == typeof(DateTime))
    {
        return (ResultType)(object)FetchDateTime(field);
    }
    if (type == typeof(DateOnly))
    {
        return (ResultType)(object)FetchDateOnly(field);
    }
    throw new NotImplementedException($"this[field: {field}]");
}

结果:

C.Fetch2[[System.DateTime, System.Private.CoreLib]](System.String)
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: xor eax, eax
    L0005: mov [edx], eax
    L0007: mov [edx+4], eax
    L000a: pop ebp
    L000b: ret 4

这是运行时使用的模式。

See on SharpLab .

关于使用模板化类型的 C# 模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76818244/

相关文章:

c# - 在运行时更改 App.Config 后 Entity Framework ConnectionString 不会更新

php - 从 CakePHP 切换到 Ruby on Rails 有什么技巧吗?

c# - 未安装相应Office版本如何获取特定Excel对象库

c# - 将两个 Lambda/Linq 查询添加在一起

c# - 更改 IQueryable 的 DataContext

c# - Asp.Net:在服务器端恢复DropDownList的客户端SelectedItem

c++ - 开关盒中的多个条件?

R - 使用带有逻辑值的开关

PHP 带有 switch case 和字符串 '-0' 的奇怪行为

javascript - 在 coffeescript 中使用 switch 进行变量赋值