2015-05-02 4 views
1

Я пишу простой алгоритм hillclimber в C# и пытаюсь следующий подход:Как скопировать объект по значению, а не по ссылке в C#

Получить начальное решение
решения копирования на новый объект
Применить алгоритм для копирования
Сравнить значение obj исходного решения с значением obj копии
если лучше - скопируйте обратно в исходное решение.

Мне известно о том, что эта тема была затронута в предыдущем посте и попыталась реализовать предложение там - Использование класса IClonable. Это то, что я пробовал:

мое решение Класс:

class Solution : ICloneable 
{ 

    public Dictionary<Room, List<Patient>> solution { get; set; } 


    public Solution() 
    { 
     solution = new Dictionary<Room, List<Patient>>(); 

    } 
    public object Clone() 
    { 
     return this.MemberwiseClone(); 
    } 
} 

Алгоритм:

public static void swap (Solution solution, Output input, Random rand) 
    { 


     Solution intSoln = new Solution(); 
     intSoln = (Solution)solution.Clone(); 

//Moving things around in intSoln here 

     Console.WriteLine("new solution = " + objValue(intSoln, input)); 
     Console.WriteLine("old solution = " + objValue(solution, input)); 
     if (objValue(intSoln, input) < objValue(solution, input)) 
     { 
      solution = (Solution)intSoln.Clone(); 
     } 
    } 

Глядя на отпечатках для старых и новых решений, они всегда одинаковы, что означает, что код явно копируется по ссылке. Я совершенно застрял и не уверен, что делать. Любая помощь приветствуется.

+0

Рассматривали ли вы использование [неизменяемых коллекций] (https://msdn.microsoft.com/en-us/library/dn385366.aspx) вместо клонирования? – CodesInChaos

ответ

3

MemberwiseClone будет делать неполную копию, что означает, что вы получите новый экземпляр, чьи поля имеют те же ссылки, что и исходный объект.

Вы хотите сделать глубокую копию вместо этого. Вот копия с еще на один уровень:

public object Clone() 
{ 
    var copy = new Solution(); 

    foreach (var pair in solution) 
     copy.solution.Add(pair.Key, pair.Value); 

    return copy; 
} 

Это скопирует словарь, но его ключи и значения будет еще указует на одни и те же случаи. Таким образом, Вы сможете выполнить более глубокую копию с чем-то вроде этого:

public object Clone() 
{ 
    var copy = new Solution(); 

    foreach (var pair in solution) 
     copy.solution.Add(new Room(pair.Key), pair.Value.ToList()); 

    return copy; 
} 

Или:

public object Clone() 
{ 
    var copy = new Solution(); 

    foreach (var pair in solution) 
     copy.solution.Add(new Room(pair.Key), pair.Value.Select(i => new Patient(i)).ToList()); 

    return copy; 
} 

Вам нужно написать некоторые конструкторы копирования для Room и Patient для этого. Надеюсь, вы получите эту идею.

+0

Спасибо! Это решило это :) – bml

0

Вам необходимо сделать глубокое клонирование типа Solution. Так Реализовать ICloneable интерфейс:

public class Solution : ICloneable 
{ 
    public object Clone() 
    { 
    // creating a new dictionnary 
    } 
} 
Смежные вопросы