読者です 読者をやめる 読者になる 読者になる

Array.ForEach メソッドに Console.WriteLine を渡すのが分からない → Action<int> で解決

Array.ForEach, List<T>.ForEach の練習。

Console.WriteLine を、引数には渡せるけれども、一時変数には代入できないのはなぜだろう。

using System;
using System.Collections.Generic;
using System.Linq;

class TestForeach {
    static void Main() {
        int[] xs = { 344, 32, 4 };
        var ys = new List<int>(xs);

        // これはOK
        Array.ForEach(xs, Console.WriteLine);
        ys.ForEach(Console.WriteLine);

        // これはだめ(コンパイルエラー)
        var fn = Console.WriteLine;
        ys.ForEach(fn);
    }
}

mcs でコンパイルすると以下のようなコンパイルエラーが表示されます。

% mcs foreach.cs
foreach.cs(15,9): error CS0815: An implicitly typed local variable declaration cannot be initialized with `method group'
foreach.cs(16,12): error CS1502: The best overloaded method match for `System.Collections.Generic.List<int>.ForEach(System.Action<int>)' has some invalid arguments
foreach.cs(16,20): error CS1503: Argument `#1' cannot convert `method group' expression to type `System.Action<int>'
Compilation failed: 3 error(s), 0 warnings

追記

ぼっつー (id:fa11enprince) さんから、Action<int> を使うと一時変数に代入できると教えていただきました。感謝です!

using System;
using System.Collections.Generic;
using System.Linq;

class TestForeach {
    static void Main() {
        int[] xs = { 344, 32, 4  };
        var ys = new List<int>(xs);

        // これはOK
        Array.ForEach(xs, Console.WriteLine);
        ys.ForEach(Console.WriteLine);

        // これはだめ(コンパイルエラー)
        // var fn = Console.WriteLine;
        // ys.ForEach(fn);

        // Action<T> デリゲート。これはOK
        Action<int> fn = Console.WriteLine;
        ys.ForEach(fn);
    }
}