C# 如何在不知道items泛型类型参数的情况下复制作为泛型给出的列表?

C# 如何在不知道items泛型类型参数的情况下复制作为泛型给出的列表?,c#,list,generics,shallow-copy,C#,List,Generics,Shallow Copy,我得到的结果是: T clone(T source) { if(source != null && source.GetType() == typeof(List<>)) { Type listType = source.GetType(); Type listElemType = listType.GetGenericArguments()[0].GetType(); var listClone = (

我得到的结果是:

T clone(T source)
{
    if(source != null && source.GetType() == typeof(List<>))
    {
        Type listType = source.GetType();
        Type listElemType = listType.GetGenericArguments()[0].GetType();
        var listClone = (T)Activator.CreateInstance(listType.MakeGenericType(listElemType));
        ...
        return listClone;
    }
    ...
}
T克隆(T源)
{
if(source!=null&&source.GetType()==typeof(List))
{
类型listType=source.GetType();
类型ListLemType=listType.GetGenericArguments()[0].GetType();
var listClone=(T)Activator.CreateInstance(listType.MakeGenericType(ListLemType));
...
返回列表克隆;
}
...
}

现在,如何填充克隆?正如我所说,我只需要一份浅显的副本。谢谢。

我不知道你为什么需要这个功能。大概
T
是某种
列表,您在编译时就知道这一点。在这种情况下,您所需要的只是
var listClone=myList.toList()

您可以根据具体情况使用反射和专用方法来实现目标,如下所示:

static public T Clone<T>(T source)
{
  if ( source == null ) return default;
  var typeSource = source.GetType();
  if ( typeSource.GetGenericTypeDefinition() == typeof(List<>) )
  {
    var typeItems = typeSource.GetGenericArguments()[0];
    var args = new[] { typeItems };
    var name = nameof(Program.Clone);
    var method = typeof(Program).GetMethod(name).MakeGenericMethod(args);
    return (T)method?.Invoke(null, new object[] { source });
  }
  else
    throw new NotImplementedException($"Clone<{typeSource.Name}>");
    // or return source.RawClone();
}
输出

1,2,3,4,5
10, 20, 30, 40, 50

如果
T
已经是
List
,则不需要重新生成该类型。但是这个方法是如何调用的呢?这是一种糟糕的代码气味。如果使用泛型,则应指定约束,以便不需要使用反射。如果列表中的类型是引用类型,则需要相同的引用还是新的引用?克隆一个值类型充其量是学术性的,克隆一个引用类型可能会非常困难。@Erik Philips OP要求提供。@OlivierRogier您知道浅拷贝的技术定义,我不确定OP是否正确。我可能应该问问他是否知道这个术语,否则只需要一个简单的
ToList()
。@ErikPhilips我不认为OP可以用这个副本来回答这个问题。OP让我发现了技术表达,因此OP应该意识到,特别是因为OP坚持这个术语。
static public List<T> Clone<T>(List<T> source)
{
  return source.ToList();
  // or return source.Select(item => item.RawClone()).ToList();
}
static public T RawClone<T>(this T instance)
{
  if ( instance == null ) throw new NullReferenceException();
  if ( !instance.GetType().IsSerializable ) throw new SerializationException();
  using ( var stream = new MemoryStream() )
  {
    var formatter = new BinaryFormatter();
    formatter.Serialize(stream, instance);
    stream.Position = 0;
    return (T)formatter.Deserialize(stream);
  }
}
var list = new List<int> { 1, 2, 3, 4, 5 };
var copy = Clone(list);

for ( int index = 0; index < copy.Count; index++ )
  copy[index] *= 10;

Console.WriteLine(string.Join(", ", list));
Console.WriteLine(string.Join(", ", copy));