83987


あるライブラリのコードを調査していて、`(ReadOnly)Memory<T>` という型の存在を知りました。  
次のようなコードを考えています。

[code]

    using System;
    
    internal class Program
    {
        static void f1(Memory<int> data)
        {
            Console.WriteLine(data);
        }
    
        static void f2(ReadOnlyMemory<int> data)
        {
            Console.WriteLine(data);
        }
    
        static void f3<T>(ReadOnlyMemory<T> data)
        {
            Console.WriteLine(data);
        }
    
        static void Main(string[] args)
        {
            int[] array = new[] { 0x42, 0x43, 0x44 };
    
            // case 1. OK
            f1(new Memory<int>(array));
            // case 2. OK
            f2(new ReadOnlyMemory<int>(array));
            // case 3. NG
            //f1(new ReadOnlyMemory<int>(array));
            // case 4. OK...?
            f2(new Memory<int>(array));
            // case 5. OK
            f1(array.AsMemory());
            // case 6. OK...?
            f2(array.AsMemory());
    
            //----------------------
    
            // case 7. OK, why??
            f1(array);
            // case 8. OK, why??
            f2(array);
            // case 9. NG, why??
            //f3(array);
        }
    }
    
[/code]

ここで、case 1-6 はおおむね予想の範囲でしたが、それに対して

  * case 7,8 がコンパイルエラーにならない理由
  * ↑を踏まえたうえで、case 9 がコンパイルエラーになる理由

を知りたいです。

補足: `.csproj`

[code]

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
      </PropertyGroup>
    </Project>
    
[/code]


CC BY-SA 4.0
2021-12-06T14:51:04.553
83981
2021-12-07T03:16:49.293
question
c# .net
型 T[] は (ReadOnly)Memory<T> に代入可能？


### case 7,8 がコンパイルエラーにならない理由

[code]

    public static implicit operator Memory<T> (T[]? array);
    public static implicit operator ReadOnlyMemory<T> (T[]? array);
    
[/code]

が存在し暗黙の型変換が行われるからです。（[`Implicit(T[] to
Memory<T>)`](https://docs.microsoft.com/ja-
jp/dotnet/api/system.memory-1.op_implicit?view=net-6.0#System_Memory_1_op_Implicit_T____System_Memory__0_)と[`Implicit(T[]
to ReadOnlyMemory<T>)`](https://docs.microsoft.com/ja-
jp/dotnet/api/system.readonlymemory-1.op_implicit?view=net-6.0#System_ReadOnlyMemory_1_op_Implicit_T____System_ReadOnlyMemory__0_)）

### case 9 がコンパルエラーになる理由

`Implicit(T[] to
ReadOnlyMemory<T>)`が定義されているのは`ReadOnlyMemory<T>`側であり、`Array`ではありません。そのため、

[code]

    int[] → ReadOnlyMemory<int>
    
[/code]

への変換はできますが、

[code]

    int[] → ReadOnlyMemory<T>
    
[/code]

への変換はできません。`f3<int>`と型を明示することで要求される引数も`ReadOnlyMemory<T>`から`ReadOnlyMemory<int>`と明示されるため、変換可能となり呼び出しも可能になります。

もし、`Implicit(T[] to
ReadOnlyMemory<T>)`が`Array`側に定義されていたら型推論できたのですが、こればっかりは仕方がないかと。


CC BY-SA 4.0
2021-12-07T00:28:56.230
83987
2021-12-07T03:16:49.293
2021-12-07T03:16:49.293
4236
4236
83981
answer