我有一个对象类TimeDuration
。当我尝试更改从数组Span获取的对象的值时,数组内的值也会更改。如何获取不会更改其父对象值的对象的副本?我需要将此副本传递给另一个函数,我必须对此对象进行更改
public void test()
{
List<TimeDuration> Span = new List<TimeDuration>();
TimeDuration ob = new TimeDuration();
ob.FromTime = DateTime.Now;
ob.ToTime = DateTime.Now.AddDays(1);
Span.Add(ob);
//Trying to assign value here!
TimeDuration ob2= Span[1];
ob2.FromTime = DateTime.Now.AddDays(3);
}
public class TimeDuration
{
public DateTime FromTime { get; set; }
public DateTime ToTime { get; set; }
}
答案 0 :(得分:6)
首先,您应该理解当前代码的行为方式。有关详细信息,请参阅my article on reference types and value types。
如何获取不会更改其父对象值的对象的副本?
两个简单的选择:
object.MemberwiseClone
作为快捷方式。在许多情况下,它很简单,虽然继承使其更难。让您的TimeDuration
类不可变,例如使用WithToTime
返回的方法
一个新版本:
public TimeDuration WithFromTime(DateTime newFromTime)
{
return new TimeDuration(newFromTime, ToTime);
}
您将属性设置为只读,并提供一个构造函数来获取两个值(也可以验证它们)。你甚至可以考虑使它成为一个结构。
答案 1 :(得分:1)
考虑将类转换为结构,当然也使它成为不可变的:
public struct TimeDuration
{
public DateTime FromTime { get; private set; }
public DateTime ToTime { get; private set; }
public TimeDuration(DateTime fromTime, DateTime toTime) : this()
{
FromTime = fromTime;
ToTime = toTime;
}
public TimeDuration SetFromTime(DateTime fromTime)
{
var copy = this;
copy.FromTime = fromTime;
return copy;
}
public TimeDuration SetToTime(DateTime toTime)
{
var copy = this;
copy.ToTime = toTime;
return copy;
}
}
答案 2 :(得分:1)
让TimeDuration
成为struct
而非class
:值类型按值传递,因此您将获得一种“复制”行为。
答案 3 :(得分:0)
类是引用类型。数组内部的值是指向TimeDuration
对象的内存位置的指针,而不是它的新实例。因此,当您更改值时,它也会影响数组。
您必须创建一个TimeDuration的新对象并传递它。
答案 4 :(得分:0)
如果您始终以这种方式使用TimeDuration
,则可以考虑将其从class
更改为struct
。要复制class
,您应该实施ICloneable并调用Clone
方法。