2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

c#のclass、ヒープに乗らないSpan作成方法

Last updated at Posted at 2025-04-28

クラスのスパンを作る

以下のコードはエラーになります。

// Cはクラスという想定
C c0 = new C();
C c1 = new C();
Span<C> span = stackalloc C[]{ c0, c1 };// エラー
SomeMethod(span);

回避法(c#12以降)

Span<C> span = [c0,c1];

検証

ChatGPTに上記のコードについて聞いたところ、内部的に配列に変換されているからコンパイルが通るといわれました。そんなわけないだろと思って、SharpLabで以下のコードのコンパイルをして、アセンブリをChatGPTに読んでもらいました。

結果的に、配列を使っていないのでヒープを使わないと言われました。アセンブリ読める方は読んで確かめて下さい。

テストコード(コメントの指摘によって修正)

using System;
public class C {
    public int age =20;
}
public static class Test{
    public static void Case0()
    {
        Span<C> span = [new C(),new C()];
        SpanMethod(span);
    }
    public static void Case1()
    {
        Span<C> span = new C[]{new C(),new C()};
        SpanMethod(span);
    }    
        
    public static void SpanMethod(Span<C> span){
        foreach(var c in span)Console.Write(c.age);
    }
}

アセンブリ

; Core CLR 9.0.124.61010 on x64

C..ctor()
    L0000: mov dword ptr [rcx+8], 0x14
    L0007: ret

Test.Case0()
    L0000: push rbx
    L0001: sub rsp, 0x40
    L0005: vxorps xmm4, xmm4, xmm4
    L0009: vmovdqu [rsp+0x20], ymm4
    L000f: mov rbx, 0x7fff5c69cc58
    L0019: mov rcx, rbx
    L001c: call 0x00007fff6ba17690
    L0021: mov dword ptr [rax+8], 0x14
    L0028: mov [rsp+0x30], rax
    L002d: mov rcx, rbx
    L0030: call 0x00007fff6ba17690
    L0035: mov dword ptr [rax+8], 0x14
    L003c: mov [rsp+0x38], rax
    L0041: lea rcx, [rsp+0x30]
    L0046: mov [rsp+0x20], rcx
    L004b: mov dword ptr [rsp+0x28], 2
    L0053: lea rcx, [rsp+0x20]
    L0058: call 0x00007fff5c6a0150
    L005d: nop
    L005e: add rsp, 0x40
    L0062: pop rbx
    L0063: ret

Test.Case1()
    L0000: push rsi
    L0001: push rbx
    L0002: sub rsp, 0x38
    L0006: xor eax, eax
    L0008: mov [rsp+0x28], rax
    L000d: mov rcx, 0x7fff5c69e150
    L0017: mov edx, 2
    L001c: call 0x00007fff6ba17850
    L0021: mov rbx, rax
    L0024: mov rsi, 0x7fff5c69cc58
    L002e: mov rcx, rsi
    L0031: call 0x00007fff6ba17690
    L0036: mov dword ptr [rax+8], 0x14
    L003d: lea rcx, [rbx+0x10]
    L0041: mov rdx, rax
    L0044: call 0x00007fff0bd10010
    L0049: mov rcx, rsi
    L004c: call 0x00007fff6ba17690
    L0051: mov dword ptr [rax+8], 0x14
    L0058: lea rcx, [rbx+0x18]
    L005c: mov rdx, rax
    L005f: call 0x00007fff0bd10010
    L0064: add rbx, 0x10
    L0068: mov [rsp+0x28], rbx
    L006d: mov dword ptr [rsp+0x30], 2
    L0075: lea rcx, [rsp+0x28]
    L007a: call 0x00007fff5c6a0150
    L007f: nop
    L0080: add rsp, 0x38
    L0084: pop rbx
    L0085: pop rsi
    L0086: ret

Test.SpanMethod(System.Span`1<C>)
    L0000: push rdi
    L0001: push rsi
    L0002: push rbx
    L0003: sub rsp, 0x20
    L0007: mov rbx, [rcx]
    L000a: mov esi, [rcx+8]
    L000d: test esi, esi
    L000f: jle short L002e
    L0011: xor edi, edi
    L0013: mov rcx, [rbx+rdi]
    L0017: mov ecx, [rcx+8]
    L001a: mov rax, 0x29e289c48a0
    L0024: call qword ptr [rax]
    L0026: add rdi, 8
    L002a: dec esi
    L002c: jne short L0013
    L002e: add rsp, 0x20
    L0032: pop rbx
    L0033: pop rsi
    L0034: pop rdi
    L0035: ret

<PrivateImplementationDetails>.InlineArrayAsSpan[[, _, , _]](...)
    ; Open generics cannot be JIT-compiled.
    ; However you can use attribute SharpLab.Runtime.JitGeneric to specify argument types.
    ; Example: [JitGeneric(typeof(int)), JitGeneric(typeof(string))] void M<T>() { ... }.

<PrivateImplementationDetails>.InlineArrayElementRef[[, _, , _]](...)
    ; Open generics cannot be JIT-compiled.
    ; However you can use attribute SharpLab.Runtime.JitGeneric to specify argument types.
    ; Example: [JitGeneric(typeof(int)), JitGeneric(typeof(string))] void M<T>() { ... }.

2
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?