C#でジェネリックリストのクローンを作成するには?

C#でオブジェクトの一般的なリストを作成し、そのリストをクローンしたいと考えています。リスト内のアイテムはクローン可能ですが、list.Clone()を実行するオプションはないようです。

これを回避する簡単な方法はありますか?

要素が値型であれば、そのままでOKです。

List newList = new List(oldList);

しかし、それらの要素が参照型であり、ディープコピーが必要な場合(要素が適切に ICloneable を実装していると仮定した場合)、次のようにすることができます。

List oldList = new List();
List newList = new List(oldList.Count);

oldList.ForEach((item) =>
    {
        newList.Add((ICloneable)item.Clone());
    });

もちろん、上記のジェネリックで ICloneable を置き換えて、ICloneable を実装している要素の型であれば何でもキャストします。

もしあなたの要素タイプが ICloneable をサポートしていなくても、コピーコンストラクタを持っている場合は、代わりにこのようにすることができます。

List oldList = new List();
List newList = new List(oldList.Count);

oldList.ForEach((item)=>
    {
        newList.Add(new YourType(item));
    });

個人的には、すべてのメンバーのディープコピーを保証する必要があるため、ICloneableは避けたいと思っています。その代わりに,コピーコンストラクタか,YourType.CopyFrom(YourType itemToCopy) のようなファクトリメソッドで,YourType の新しいインスタンスを返すことをお勧めします.

これらのオプションのいずれも,(拡張機能やその他の)メソッドでラップすることができます。

解説 (21)

浅いコピーの場合は、代わりにジェネリックなListクラスのGetRangeメソッドを使うことができます。

List oldList = new List( );
// Populate oldList...

List newList = oldList.GetRange(0, oldList.Count);

引用元:ジェネリック・レシピより

解説 (2)

値の型だけを気にするなら...。

型を知っていて

List newList = new List(oldList);

前に型を知らない場合は、ヘルパー関数が必要になります。

List Clone(IEnumerable oldList)
{
    return newList = new List(oldList);
}

だけです。

List myNewList = Clone(myOldList);
解説 (2)