BMS, Movie, Illustrations, Programming

[C#] IEnumerable は必ずしも読み取り専用(readonly)ではないが、読み取り専用として扱うべきである

通常、IEnumerable<T> は読み取り専用のコレクションとして用いられます。

しかしながら、IEnumerable<T> の実体が T[] や List<T> であった場合は、キャストすると中身を変更することが出来ます。(以下のコードを参照)

ですが、最初に述べた通り、IEnumerable<T> は読み取り専用として用いるべきものですので、この型で受け取ったものは変更するべきではありません。

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

public class Test
{
    public static void FunctionWhichChangesArgument(IEnumerable<int> arr) 
    {
        // 書き込み可能な型にキャスト
        if(arr is int[]) 
        {
            ((int[])arr)[1] = 100;
        }
    }

    public static void Main()
    {
        var arr = new int[] { 1, 2, 3 };
        Console.WriteLine("Before: " + String.Join(",", arr));
        FunctionWhichChangesArgument(arr);  // 変更!!
        Console.WriteLine("After: " + String.Join(",", arr));
    }
}

参考:How to make IEnumerable<T> readonly? – Stack Overflow

If we’re going to get technical about what you can do, you can also use reflection to access any class’ private members and do whatever you want. Just because you can do something (like cast IEnumerable to its actual type) doesn’t mean you ever should.

IEnumerable は変更すべきではなく、読み取り専用として用いるべき(意訳)と書いてあります(多分)。


そもそもリフレクションを使えば private なメンバにもアクセスできるので今更ですけどね。