使用复制的属性复制对象或新对象?

时间:2012-08-26 20:27:34

标签: c# visual-studio-2010 oop

我正在制作一个文件备份程序,使用配置文件来保存设置等。目前结构是这样的:

MainForm有一个ProfileHandler,其中有一堆个人资料对象

当您对程序进行任何更改(将文件添加到列表,更改目标路径等)时 - 设置将保存在临时配置文件中。到目前为止,这么好......

但是当我想保存个人资料时,我无法真正决定走哪条路。现在我将临时配置文件对象传递给AddProfile中的ProfileHandler方法。然后,该方法使用临时配置文件对象中的属性作为参数创建新的配置文件对象(List<string>除外,它只使用Addrange复制内容)。

它有效,但它好吗?

public bool AddProfile(Profile tempProfile)
{
    if (tempProfile != null)
    {
        Profile profile = new Profile(tempProfile.Name, tempProfile.TargetPath);
        profile.Filelist.Clear();
        profile.Filelist.AddRange(tempProfile.Filelist);
        _profiles.Add(profile);
    }
    return (tempProfile != null);
}

有没有更明智的方式呢? 不知何故,我觉得必须有一种简单的方法来创建Profile对象的新实例,它是tempProfile的简单副本。在我的情况下,Profile类只有三个字段,这使得它很容易,但是如果它有大量的话呢?

我希望我不太清楚。我有点新鲜。

3 个答案:

答案 0 :(得分:1)

您可以对tempProfile进行深层复制并保存。 这是示例代码 来源How do you do a deep copy of an object in .NET (C# specifically)?

public static T DeepClone<T>(T obj)
{
 using (var ms = new MemoryStream())
 {
   var formatter = new BinaryFormatter();
   formatter.Serialize(ms, obj);
   ms.Position = 0;

   return (T) formatter.Deserialize(ms);
 }
}

答案 1 :(得分:1)

只需创建一个构造函数,它接受一个Profile并像这样复制:

public Profile(Profile profileToCreateFrom)
    : this(profileToCreateFrom.Name, profileToCreateFrom.TargetPath)
{
    FileList = profileToCreateFrom.FileList.Select(file => file).ToList();
}

然后添加新的:

_profiles.Add(new Profile(tempProfile));

答案 2 :(得分:1)

您可以查看受保护的object.MemberwiseClone方法。这种方法从早期开始就存在。

void Main()
{
    Profile p = new Profile("bob", @"c:\foo");
    p.FileList.Add("bar.txt");

    Profile copy = p.DeepCopy();
    copy.FileList.Clear();
    copy.FileList.Add("baz.log");

    p.Dump("p");
    copy.Dump("copy");
}

public class Profile
{
    public Profile(string name, string targetPath)
    {
        this.Name = name;
        this.TargetPath = targetPath;
        this.FileList = new List<string>();
    }

    public Profile DeepCopy()
    {
        Profile copy = (Profile)this.MemberwiseClone(); // this takes care of Name & TargetPath
        copy.FileList = new List<string>(this.FileList);
        return copy;
    }

    public string Name { get; private set; }
    public string TargetPath { get; private set; }
    public List<string> FileList { get; private set; }
}

您可以将MemberwiseClone视为进行浅位按复制。对于像int,double,float这样的值类型,甚至对于像string这样的不可变引用类型,这通常是可以的。但是,您需要在配置文件类中创建可变引用类型(如List<string>)的副本,以便副本的突变也不会更改原始类型。就维护而言,这是一种细节 - 如果你添加一个新的可变属性,你必须记住在克隆发生后在深拷贝方法中复制。

根据您的设计,可能还有其他事项,例如您可能不想复制的事件注册。您可以将这些视为瞬变。如果您的应用程序是多线程的,您也需要谨慎,在复制过程中,您必须在其他地方采取同样的措施来维护对象的完整性(例如,锁定。)

我没有表现号码。无论你采取什么建议,你最适合做自己的一些性能测试,看看它是否足够快。