こんにちは:) winFormに他のオブジェクトとリストを含むオブジェクトのクローンを作成するときに問題が発生しました。タイプ構造のオブジェクトの クローンを作成したいクラスを以下に示します まず、ShallowCloneを試しました
public Structure Clone()
{
return this.MemberwiseClone() as Structure;
}
それが機能しなかったので、https://stackoverflow.com/を検索し、ディープクローンを作成しました
オブジェクトのクローン作成 とこれ .NET(具体的にはC#)でオブジェクトのディープコピーをどのように実行しますか?
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);
}
}
私が抱えている問題は、オブジェクトのバックアップコピーを取っていることです
var backup=DeepClone<Structure>(this.sched); //sched is Structure Object
その後this.sched
、バックアップの変更が変更されます:(
私のクラスの構造は次のとおりです。
[Serializable]
public class Sub
{
string name;
int studentsNumber;
int unassaignedStudent;
public Sub(string name, int number)
{
this.name = name;
this.studentsNumber = number;
this.unassaignedStudent = number;
}
public Subject()
{
this.name = "";
this.studentsNumber = 0;
this.unassaignedStudent = 0;
}
public bool Assigne(int count)
{
//stuff
}
public Sub Clone()
{
return this.MemberwiseClone() as Sub;
}
}
[Serializable]
class Room
{
string name;
int studentsNumber;
int full;
private int freeSeats;
List<Sub> subjects;
/// <summary>
/// the list of subjects
/// </summary>
internal List<Sub> Subjects
{
get { return subjects; }
set { subjects = value; }
}
Dictionary<Subject, int> variations;
public Room(string name, int number)
{
this.name = name;
this.studentsNumber = number;
this.full = 0;
this.subjects = new List<Subject>();
this.variations = new Dictionary<Subject, int>();
this.freeSeats = number;
}
public Room(int number)
{
this.studentsNumber = number;
this.full = 0;
this.subjects = new List<Subject>();
this.variations = new Dictionary<Subject, int>();
this.freeSeats = number;
}
public Room()
{
this.name = "R" + count.ToString();
count++;
this.studentsNumber = 0;
this.full = 0;
this.subjects = new List<Sub>();
this.variation= new Dictionary<Sub, int>();
this.freeSeats = 0;
}
public bool addSubject(Sub sbj)
{
//also stuff
}
public bool addPartialSubject(Sub sbj)
{
//stuff
// return false;
}
public Room Clone()
{
return this.MemberwiseClone() as Room;
}
}
[Serializable]
class Period
{
List<Room> rooms;
int conflicts;
List<Sub> subjects;
internal List<Sub> Subjects
{
get { return subjects; }
set { subjects = value; }
}
/// <summary>
/// Create an instance of class Period
/// </summary>
/// <param name="rooms">the rooms in this Period</param>
public Period(List<Room> rooms)
{
this.conflicts = 0;
this.rooms = rooms;
subjects = new List<Subject>();
fillSubjects(ref rooms, ref subjects);
}
public Period()
{
this.conflicts = 0;
this.rooms = null;
subjects = new List<Subt>();
freeSeats = 0;
}
/// <summary>
/// Fill the subjects in the rooms to the list of subjects
/// </summary>
/// <param name="rooms">referance to the list of the rooms</param>
/// <param name="subjects">referance to the list of the subjects</param>
private void fillSubjects(ref List<Room> rooms, ref List<Sub> subjects)
{
foreach (var room in rooms)
{
foreach (var subject in room.Subjects)
{
if (!subjects.Exists(s => s.Name == subject.Name))
subjects.Add(subject);
}
}
}
/// <summary>
/// Adds the given subject to the period if there is a place in any room
/// </summary>
/// <param name="s">the subject to add</param>
/// <returns>true if there is space for this subject and added, otherwise false</returns>
public bool AddSubject(Sub s)
{
foreach (var room in rooms)
{
if (room.addSubject(s))
{
//stuff
}
else
if (room.addPartialSubject(s))
{
//stuff
}
}
return false;
}
private int CalculateConflictions(Sub s)
{
//also a lot of stuff
}
}
[Serializable]
class Structure:IDisposable
{
int days;
/// <summary>
/// the number of days in the Schedual
/// </summary>
public int Days
{
get { return days; }
set { days = value; }
}
int periods;
Period[,] schedualArray;
List<Room> rooms;
internal List<Room> Rooms
{
get { return rooms; }
set { rooms = value; }
}
/// <summary>
/// Creates an instance of the Structure object
/// </summary>
/// <param name="rooms">a list of the rooms in the Schedual</param>
public Structure(int days, int periods,List<Room> rooms)
{
this.days = days;
this.periods = periods;
this.rooms=rooms;
this.schedualArray = new Period[days, periods];
this.subjectCount = 0;
for (int i = 0; i < days; i++)
{
for (int j = 0; j < periods; j++)
{
schedualArray[i, j] = new Period(CloneList(ref rooms)); //here i cloned the list to be in the safe side and it didn't work also
}
}
}
public Structure()
{
this.days = 0;
this.totalEval = Int32.MaxValue;
this.periods = 0;
this.rooms = null;
this.subjectCount = 0;
this.schedualArray = null;
}
internal bool AddSubject(Sub subject, int day, int period)
{
//add the subject into inner lists (room)
}
public void PrintStruct()
{
for (int i = 0; i < days; i++)
{
for (int j = 0; j < periods; j++)
{
foreach (var subject in schedualArray[i, j].Subjects)
{
Console.Write("\t\t");
}
Console.Write("\t\t");
}
Console.WriteLine();
}
}
public Structure Clone()
{
return this.MemberwiseClone() as Structure;
}
public List<Room> CloneList(ref List<Room> rooms)
{
var lst = new List<Room>();
foreach (var room in rooms)
{
lst.Add(DeepClone<Room>(room));
}
return lst;
}
internal void RemoveSubject(Sub subject)
{
//..................
}
#region IDisposable Members
public void Dispose()
{
GC.Collect(g, GCCollectionMode.Forced);
}
#endregion
}
クローン作成プロセスの詳細はわかりませんが、オブジェクトの構造と階層内の連続するオブジェクトと、リストが参照しているだけでなく、リストが指す完全なアイテムを使用して、オブジェクト全体をクローンする必要があり ます。誰かが私を助けてください私は本当に迷っています:(、私を助けてくれることに興味を持っているすべての人に事前に感謝します:) Yaser
メソッド@WiiMaxxを使用する場合は編集
Structure backup=XamlClone(this.sched);
private Structure XamlClone(Structure s)
{
//First Step
// create a XAML string
string stCopie = XamlWriter.Save(s);
//Secound Step
// convert him back to an Object of YourTyp
return XamlReader.Load(XmlReader.Create(new StringReader(stCopie))) as Structure;
}
しかし、内部period[,]
は次のように複製されます。 @WiiMaxxnull
を助けてください。
Edit 2.0
私は3つのメソッドでのディープクローンについてもこの記事をチェックしましたが、コードに循環参照があると思います。そのため、これは機能しません
http://blog.nuclex-games.com/mono-dotnet/ fast-deep-cloning /
End Edit