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));