2

Collection<T>T実行時のみ (コンパイル時ではなく) 既知である を指定すると、 を生成したいと思いImmutableList<T>ます。

作成したいメソッドは次のようになります。

var immutableList = CreateImmutableList(originalList, type);

ここで、originalList はIEnumerable、type はT生成されたのImmutableList<T>です。

どのように?!

(私はNET .Coreで作業しています)

編集:コメントのおかげで、実用的な解決策が見つかりました。AddRange メソッドを使用します。

namespace Sample.Tests
{
    using System;
    using System.Collections;
    using System.Collections.Immutable;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Reflection;
    using Xunit;

    public class ImmutabilityTests
    {
        [Fact]
        public void CollectionCanBeConvertedToImmutable()
        {
            var original = new Collection<object>() { 1, 2, 3, 4, };
            var result = original.AsImmutable(typeof(int));

            Assert.NotEmpty(result);
            Assert.IsAssignableFrom<ImmutableList<int>>(result);
        }
    }

    public static class ReflectionExtensions
    {
        public static IEnumerable AsImmutable(this IEnumerable collection, Type elementType)
        {
            var immutableType = typeof(ImmutableList<>).MakeGenericType(elementType);
            var addRangeMethod = immutableType.GetMethod("AddRange");
            var typedCollection = ToTyped(collection, elementType);

            var emptyImmutableList = immutableType.GetField("Empty").GetValue(null);
            emptyImmutableList = addRangeMethod.Invoke(emptyImmutableList, new[] { typedCollection });
            return (IEnumerable)emptyImmutableList;
        }

        private static object ToTyped(IEnumerable original, Type type)
        {
            var method = typeof(Enumerable).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(type);
            return method.Invoke(original, new object[] { original });
        }
    }
}
4

3 に答える 3

0

ボックス化/ボックス化解除の準備ができている場合は、次のようなことができます

           var objectCollection = new Collection<object>();
            objectCollection.Add(3);
            objectCollection.Add(4);
            var immutableList = objectCollection.ToImmutableList();

ここで要素の型はintで、オブジェクトのコレクションに値を追加します。型付けされた値を取得したい場合は、次のようにできます。

    foreach (var obj in immutableList)
                {
                    int myVal = (int) Convert.ChangeType(obj, typeof(int));
                    Console.WriteLine(myVal);
                }

注:リストが大きく、要素タイプがボックス化/ボックス化解除を所有する値型である場合、パフォーマンスに影響を与える可能性があります

于 2016-06-16T11:56:46.703 に答える