C# 实施和履行;是T x“;对于值类型

C# 实施和履行;是T x“;对于值类型,c#,.net,cil,C#,.net,Cil,我有类似的情况: interface IStorage { bool TryGetValue<T>(out T result) where T : struct; } class Storage<T> : IStorage where T : struct { readonly T value; public Storage(T val) { value = val; } public bool Try

我有类似的情况:

interface IStorage
{
    bool TryGetValue<T>(out T result) where T : struct;
}

class Storage<T> : IStorage where T : struct
{
    readonly T value;

    public Storage(T val)
    {
        value = val;
    }

    public bool TryGetValue<T2>(out T2 result) where T2 : struct
    {
        if(value is T2 val)
        {
            result = val;
            return true;
        }
        result = default;
        return false;
    }
}
结果表明,表达式不仅一次,而且两次将值装箱,
isinst
的第一次和
unbox.any
的第二次,因此它不仅隐藏装箱(通常认为很昂贵),而且还隐藏了两次

我有两个问题:有没有更好的方法来实现这种专业化?这段CIL代码虽然看起来效率很低,但是否有可能在以后的运行时通过JIT进行优化

在这种特殊情况下,我希望运行时推断出
T
T2
的唯一实例化应该返回true,并且应该忽略所有其他代码,包括检查。可能是这种情况吗?

“这段CIL代码虽然看起来效率很低,但是否有可能在稍后的运行时通过JIT进行优化?”-不,JIT代码的结果似乎也很臃肿,但需要更多的测试来验证。我的小型4.8框架编译
if(值为t2val)
to

00007FFDEF110E3D  mov         rdx,qword ptr [rbp+90h]  
00007FFDEF110E44  add         rdx,8  
00007FFDEF110E48  vmovdqu     xmm0,xmmword ptr [rdx]  
00007FFDEF110E4D  vmovdqu     xmmword ptr [rbp+40h],xmm0  
00007FFDEF110E53  lea         rdx,[rbp+40h]  
00007FFDEF110E57  mov         rcx,7FFDEF006C68h  
00007FFDEF110E61  call        00007FFE4E642570  
00007FFDEF110E66  mov         qword ptr [rbp+30h],rax  
00007FFDEF110E6A  mov         rdx,qword ptr [rbp+30h]  
00007FFDEF110E6E  mov         rcx,7FFDEF006C68h  
00007FFDEF110E78  call        00007FFE4E643D00  
00007FFDEF110E7D  test        rax,rax  
00007FFDEF110E80  je          00007FFDEF110ED7  
00007FFDEF110E82  lea         rdx,[rbp+40h]  
00007FFDEF110E86  mov         rcx,7FFDEF006C68h  
00007FFDEF110E90  call        00007FFE4E642570  
00007FFDEF110E95  mov         qword ptr [rbp+28h],rax  
00007FFDEF110E99  mov         rdx,qword ptr [rbp+28h]  
00007FFDEF110E9D  mov         rcx,7FFDEF006C68h  
00007FFDEF110EA7  call        00007FFE4E643D00  
00007FFDEF110EAC  mov         qword ptr [rbp+20h],rax  
00007FFDEF110EB0  mov         rdx,qword ptr [rbp+20h]  
00007FFDEF110EB4  mov         rcx,7FFDEF006C68h  
00007FFDEF110EBE  call        00007FFE4E6BC030  
00007FFDEF110EC3  vmovdqu     xmm0,xmmword ptr [rax]  
00007FFDEF110EC8  vmovdqu     xmmword ptr [rbp+58h],xmm0  
00007FFDEF110ECE  mov         dword ptr [rbp+38h],1  
00007FFDEF110ED5  jmp         00007FFDEF110EDC  
00007FFDEF110ED7  xor         eax,eax  
00007FFDEF110ED9  mov         dword ptr [rbp+38h],eax  
00007FFDEF110EDC  mov         eax,dword ptr [rbp+38h]  
00007FFDEF110EDF  movzx       eax,al  
00007FFDEF110EE2  mov         dword ptr [rbp+54h],eax  
00007FFDEF110EE5  cmp         dword ptr [rbp+54h],0  
00007FFDEF110EE9  je          00007FFDEF110F08  

这是使用ValueType的一个限制条件——这样的操作会变得一团糟。如果这是一个常见的用例,也许这不应该是一个结构?

您有性能问题吗?您是否希望在性能关键的情况下使用此方法?因为如果不是,那么这就是过早的优化。我不是100%确定,但是由于.net c#jit单独发出泛型代码,并且jit可以检查这个条件,所以应该从输出中忽略它。因此,我认为检查不会在运行时执行,对性能没有影响
00007FFDEF110E3D  mov         rdx,qword ptr [rbp+90h]  
00007FFDEF110E44  add         rdx,8  
00007FFDEF110E48  vmovdqu     xmm0,xmmword ptr [rdx]  
00007FFDEF110E4D  vmovdqu     xmmword ptr [rbp+40h],xmm0  
00007FFDEF110E53  lea         rdx,[rbp+40h]  
00007FFDEF110E57  mov         rcx,7FFDEF006C68h  
00007FFDEF110E61  call        00007FFE4E642570  
00007FFDEF110E66  mov         qword ptr [rbp+30h],rax  
00007FFDEF110E6A  mov         rdx,qword ptr [rbp+30h]  
00007FFDEF110E6E  mov         rcx,7FFDEF006C68h  
00007FFDEF110E78  call        00007FFE4E643D00  
00007FFDEF110E7D  test        rax,rax  
00007FFDEF110E80  je          00007FFDEF110ED7  
00007FFDEF110E82  lea         rdx,[rbp+40h]  
00007FFDEF110E86  mov         rcx,7FFDEF006C68h  
00007FFDEF110E90  call        00007FFE4E642570  
00007FFDEF110E95  mov         qword ptr [rbp+28h],rax  
00007FFDEF110E99  mov         rdx,qword ptr [rbp+28h]  
00007FFDEF110E9D  mov         rcx,7FFDEF006C68h  
00007FFDEF110EA7  call        00007FFE4E643D00  
00007FFDEF110EAC  mov         qword ptr [rbp+20h],rax  
00007FFDEF110EB0  mov         rdx,qword ptr [rbp+20h]  
00007FFDEF110EB4  mov         rcx,7FFDEF006C68h  
00007FFDEF110EBE  call        00007FFE4E6BC030  
00007FFDEF110EC3  vmovdqu     xmm0,xmmword ptr [rax]  
00007FFDEF110EC8  vmovdqu     xmmword ptr [rbp+58h],xmm0  
00007FFDEF110ECE  mov         dword ptr [rbp+38h],1  
00007FFDEF110ED5  jmp         00007FFDEF110EDC  
00007FFDEF110ED7  xor         eax,eax  
00007FFDEF110ED9  mov         dword ptr [rbp+38h],eax  
00007FFDEF110EDC  mov         eax,dword ptr [rbp+38h]  
00007FFDEF110EDF  movzx       eax,al  
00007FFDEF110EE2  mov         dword ptr [rbp+54h],eax  
00007FFDEF110EE5  cmp         dword ptr [rbp+54h],0  
00007FFDEF110EE9  je          00007FFDEF110F08