C#如何在不作为参考的情况下分配List <t>?</t>

时间:2012-11-19 03:26:42

标签: c# reference

例如

List<string> name_list1 = new List<string>();
List<string> name_list2 = new List<string>();

稍后在代码中:

name_list1.Add("McDonald");
name_list1.Add("Harveys");
name_list1.Add("Wendys");

name_list2 = name_list1; // I make a copy of namelist1 to namelist2

所以,从这一点来说,我想在不影响name_list1的情况下继续添加元素或在name_list2中进行更改。我该怎么做?

14 个答案:

答案 0 :(得分:103)

name_list2 = new List<string>(name_list1);

这将克隆列表。

答案 1 :(得分:8)

name_list2 = new List<string>(name_list1); // Clone list into a different object

此时,两个列表是不同的对象。您可以在不影响list1的情况下将项目添加到list2

答案 2 :(得分:5)

问题在于作业。在赋值name_list2 = name_list1;之前,变量name_list1name_list2指向的堆上有两个不同的List对象。你填写name_list1,这很好。但是赋值说,“make name_list2指向堆上的同一个对象name_list1。” name_list2过去指向的列表不再可访问,将被垃圾收集。您真正想要的是将name_list1内容复制到name_list2。您可以使用List.AddRange执行此操作。请注意,这将导致“浅”副本,这对于您引用的示例很好,其中列表内容是字符串,但当列表成员是更复杂的对象时可能不是您想要的。这一切都取决于你的需求。

答案 3 :(得分:5)

另一个选择是:深度克隆

public static T DeepCopy<T>(T item)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, item);
            stream.Seek(0, SeekOrigin.Begin);
            T result = (T)formatter.Deserialize(stream);
            stream.Close();
            return result;
        }

所以,

你可以使用:

name_list2 = DeepCopy<List<string>>(name_list1);

OR:

name_list2 = DeepCopy(name_list1); 

也可以。

答案 4 :(得分:2)

这是另一种解决方案:

    List<string> name_list1 = new List<string>();
    List<string> name_list2 = new List<string>();

    name_list1.Add("McDonald");
    name_list1.Add("Harveys");
    name_list1.Add("Wendys");

    name_list2.AddRange(name_list1.ToArray());

ToArray()方法复制&#39; name_list1&#39;到一个新数组,然后我们通过AddRange()方法将其添加到name_list2。

答案 5 :(得分:2)

我喜欢linq ...

如果列表元素是基元或结构,那么......

L2 = L1.ToList()

如果列表元素是类,那么......

L2 = L1.Select(x => x.Copy()).ToList();

Copy可能仅仅是MemberWiseClone的浅层复制曝光,或者可能是深层复制的一些实现。

答案 6 :(得分:1)

我更喜欢Json转换器方法来序列化和反序列化,这样你就不必标记序列化的类,特别是你有很多子类。

https://www.newtonsoft.com/json/help/html/SerializingJSON.htm

答案 7 :(得分:1)

对于原始类型:
List ClonedList = new list(OriginalList);

对于非原始/用户定义类型:
我们需要执行深层复制: Deep Copy用于制作内部引用类型的完整深层副本,为此我们需要配置MemberwiseClone()返回的对象。

Step1-在你的班级继承自ICloneable:
公共类MyClass:ICloneable

Step2-实施方法

public MyClass Clone()
{
  MyClass MyClassObj =new MyClass();
  MyClassObj.Property1 = this.Property1;
  .
  .
  MyClassObj.Property_N = this.Property_N;
  return MyClass;
}

Step3-现在克隆你的列表

List<MyClass> MyClassClone = new List<MyClass>(); 
for(i=0; i<Count; i++)
  {
      MyClassClone.Add(OriginalClaaObj[i].Clone());
  }

这将对对象的每个项目进行深层复制。

答案 8 :(得分:1)

对于基本类型,您可以执行以下操作:

List<string> CopyList = new List<string>(OriginalList);

对于非原始/用户定义的类型,您可以执行以下操作:

List<Person> CopyList = new List<Person>();
foreach(var item in OriginalList)
{
    CopyList.Add(new Person { 
            Name = item.Name,
            Address = item.Address
    });
}

答案 9 :(得分:0)

如果两个列表属于同一复杂类型,则可以执行以下操作:-

SomeClass List2 = new List();

List1.ForEach(u => List2.Add(u));

我正在做的是遍历List1的每个元素,并将其继续添加到List2。 我相信这是最短的方法。

答案 10 :(得分:0)

虽然这可能是潜在的性能威胁解决方案,但它会雄辩地逐属性复制值。

# print(df2)
   id                 cars1              cars2
0   1              OpehAdam                BMW
1   2     Opel Astra Estate  Opel Astra Estate
2   3  Opel Astra Hatchback   Opel Grandland X
3   4     Opel Astra Saloon               Audi
4   5      Opel Grandland X               Audi

答案 11 :(得分:0)

基于@Mrunal答案,我创建了一个扩展方法:

public static T Clone<T>(this T source)
    {
        // Don't serialize a null object, simply return the default for that object
        if (source == null)
        {
            return default;
        }

        // initialize inner objects individually
        // for example in default constructor some list property initialized with some values,
        // but in 'source' these items are cleaned -
        // without ObjectCreationHandling.Replace default constructor values will be added to result
        var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };

        return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
    }

您可以这样称呼它:

L2 = L1.Select(x => x.Clone()).ToList();

答案 12 :(得分:0)

这对我使用 LINQ 有用...

lst1= lst2.ToList();

答案 13 :(得分:-1)

在使用类对象列表时,以上解决方案均不适用于我。

这可用于将任何对象复制到具有共享属性名称的另一个对象。

public static void ObjectToObject(object source, object destination)
{
  // Purpose : Use reflection to set property values of objects that share the same property names.
  Type s = source.GetType();
  Type d = destination.GetType();

  const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;

  var objSourceProperties = s.GetProperties(flags);
  var objDestinationProperties = d.GetProperties(flags);

  var propertyNames = objSourceProperties
  .Select(c => c.Name)
  .ToList();

  foreach (var properties in objDestinationProperties.Where(properties => propertyNames.Contains(properties.Name)))
  {

    try
    {
      PropertyInfo piSource = source.GetType().GetProperty(properties.Name);

      properties.SetValue(destination, piSource.GetValue(source, null), null);
    }
    catch (Exception ex)
    {
      throw;
    }

  }
}


public static List<T> CopyList<T>(this List<T> lst)
{
  List<T> lstCopy = new List<T>();

  foreach (var item in lst)
  {
    var instanceOfT = Activator.CreateInstance<T>();
    ObjectToObject(item, instanceOfT);
    lstCopy.Add(instanceOfT);
  }
  return lstCopy;
}

对于列表,请使用以下命令: list2 = list1.CopyList();