gpt4 book ai didi

c# - 转换 'compile-time' 类型最快的方法是什么?

转载 作者:行者123 更新时间:2023-11-30 13:40:06 24 4
gpt4 key购买 nike

我知道标题有点含糊。但我想要实现的是这样的:

在抽象类中:

public abstract bool TryGet<T>(string input, out T output) where T : struct;

在具有此签名的类中:

private class Param<T> : AbstractParam where T : struct

这个实现:

public override bool TryGetVal<TOriginal>(string input, out TOriginal output)
{
T oTemp;
bool res = _func(input, out oTemp); // _func is the actual function
// that retrieves the value.
output = (TOriginal)oTemp; // Compile-time error
return res;
}

并且 TOriginal 将始终与 T 的类型相同。 这会绕过编译时错误,但我没有想要这样做会导致性能下降:

output = (TOriginal)(object)oTemp;

如果它是引用类型,这将提供解决方案:

output = oTemp as TOriginal;

反射/动态也可以解决这个问题,但对性能的影响更大:

output = (TOriginal)(dynamic)oTemp;

我尝试使用不安全的代码,但没有成功,但这可能就是我。

所以我最大的希望是编译器将 (TOriginal)(object)oTemp 优化为 (TOriginal)oTemp 我不知道。或者有一种不安全的方法。

让我省去关于过早优化的讲座,我想知道这纯粹是为了研究,如果有办法克服这个限制,我很感兴趣。我意识到这对实际性能的影响可以忽略不计。

最终结论:
分解情况后,结果如下:

                return (TOut)(object)_value;
00000000 push ebp
00000001 mov ebp,esp
00000003 push eax
00000004 mov dword ptr [ebp-4],ecx
00000007 cmp dword ptr ds:[003314CCh],0
0000000e je 00000015
00000010 call 61A33AD3
00000015 mov eax,dword ptr [ebp-4]
00000018 mov eax,dword ptr [eax+4]
0000001b mov esp,ebp
0000001d pop ebp
0000001e ret

return _value;
00000000 push ebp
00000001 mov ebp,esp
00000003 push eax
00000004 mov dword ptr [ebp-4],ecx
00000007 cmp dword ptr ds:[004814B4h],0
0000000e je 00000015
00000010 call 61993AA3
00000015 mov eax,dword ptr [ebp-4]
00000018 mov eax,dword ptr [eax+4]
0000001b mov esp,ebp
0000001d pop ebp
0000001e ret

事实证明,今天的编译器对此进行了优化,因此没有性能成本。

output = (TOriginal)(object)oTemp;

这是最优化的方法:)。

谢谢 Eric LippertBen Voigt .

关于引用类型的注释:
当删除 struct 约束并传递引用类型(在我的例子中是 string)时,此优化进行。

结果:

                return (TOut)(object)_value;
00000000 push ebp
00000001 mov ebp,esp
00000003 sub esp,10h
00000006 mov dword ptr [ebp-4],edx
00000009 mov dword ptr [ebp-10h],ecx
0000000c mov dword ptr [ebp-8],edx
0000000f cmp dword ptr ds:[003314B4h],0
00000016 je 0000001D
00000018 call 61A63A43
0000001d mov eax,dword ptr [ebp-8]
00000020 mov eax,dword ptr [eax+0Ch]
00000023 mov eax,dword ptr [eax]
00000025 mov dword ptr [ebp-0Ch],eax
00000028 test dword ptr [ebp-0Ch],1
0000002f jne 00000036
00000031 mov ecx,dword ptr [ebp-0Ch]
00000034 jmp 0000003C
00000036 mov eax,dword ptr [ebp-0Ch]
00000039 mov ecx,dword ptr [eax-1]
0000003c mov eax,dword ptr [ebp-10h]
0000003f mov edx,dword ptr [eax+4]
00000042 call 617D79D8
00000047 mov esp,ebp
00000049 pop ebp
0000004a ret

return _value;
00000000 push ebp
00000001 mov ebp,esp
00000003 push eax
00000004 mov dword ptr [ebp-4],ecx
00000007 cmp dword ptr ds:[003314B4h],0
0000000e je 00000015
00000010 call 61A639E3
00000015 mov eax,dword ptr [ebp-4]
00000018 mov eax,dword ptr [eax+4]
0000001b mov esp,ebp
0000001d pop ebp
0000001e ret

如果您想要一种廉价的方式转换为“无需适当的类型检查”,as 运算符就是您的解决方案。

最佳答案

我要给你上你不想听的课,因为你显然不明白。

“衡量、衡量、衡量!”有两个原因。 (或等同于“配置文件、配置文件、配置文件!”)优化方法:

  1. 将精力放在影响最大的地方。这就是术语“过早优化”的由来。

    有时这个原因不适用(当您想了解理论/出于学术原因时)。

  2. 找出哪个实现实际上更快。

现代 CPU 是复杂的野兽,由于缓存行为、管道数据依赖性、微代码等的复杂性,即使比较两个不同的机器代码序列也无法显示哪个更好。而且你正在操作比它高两个级别(C# 代码 -> MSIL -> 机器代码)。如果不进行测量,就无法确定会进行哪些优化。

你说:

This'd bypass the compile-time error, but I don't want to do this cause of the performance hit:

output = (TOriginal)(object)oTemp;

但我认为实际上没有任何性能受到影响。通用方法针对每种值类型进行 JIT 处理,该过程应该完全消除任何想象中的性能损失。但欢迎您通过性能数据(实际分析器测量)或至少通过反汇编 JIT 生成的机器代码来证明确实存在成本。


在这种特殊情况下,如果它们始终与您声明的类型相同,则不清楚为什么要以两个不同的泛型类型参数开头。只需去掉 TOriginal 并使用 T 作为输出参数的类型。

关于c# - 转换 'compile-time' 类型最快的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8954578/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com