C# 两个对象(一个在列表中<;gt;)共享相同的内存地址,即如果其中一个对象发生更改,它将更改列表中的另一个对象
我在这方面投入了大量的努力和研究,我被困住了。我尝试过复制构造函数、复制函数和Memberwise克隆函数,但这些似乎都不起作用。C# 两个对象(一个在列表中<;gt;)共享相同的内存地址,即如果其中一个对象发生更改,它将更改列表中的另一个对象,c#,list,object,memory-address,C#,List,Object,Memory Address,我在这方面投入了大量的努力和研究,我被困住了。我尝试过复制构造函数、复制函数和Memberwise克隆函数,但这些似乎都不起作用。矩阵[0]中的元素不应更改,但是g1中的更改会更改 如果有人知道如何解决这个问题,请回复 我正在添加额外的文本,以便发布我的问题 class Game { public Game() { Card_ID = 1; EmptyMainMonsterZones = 5; Empty
矩阵[0]
中的元素不应更改,但是g1
中的更改会更改
如果有人知道如何解决这个问题,请回复
我正在添加额外的文本,以便发布我的问题
class Game
{
public Game()
{
Card_ID = 1;
EmptyMainMonsterZones = 5;
EmptyExtraMonsterZones = 1;
EmptySpellTrapZones = 5;
LP = 8000;
NormalSummons = 1;
DrawnCards = 0;
LastEvent = "";
CardPool = new List<Card>();
ScenarioSteps = new List<string>();
}
public Game(Game other)
{
Card_ID = other.Card_ID;
EmptyMainMonsterZones = other.EmptyMainMonsterZones;
EmptyExtraMonsterZones = other.EmptyExtraMonsterZones;
EmptySpellTrapZones = other.EmptySpellTrapZones;
LP = other.LP;
NormalSummons = other.NormalSummons;
DrawnCards = other.DrawnCards;
LastEvent = other.LastEvent;
//CardPool = new List<Card>(other.CardPool);
CardPool = new List<Card>();
foreach (Card c in other.CardPool)
{
CardPool.Add(c);
}
//ScenarioSteps = new List<string>(other.ScenarioSteps);
ScenarioSteps = new List<string>();
foreach (string s in other.ScenarioSteps)
{
ScenarioSteps.Add(s);
}
}
public object Clone()
{
return this.MemberwiseClone();
}
int Card_ID;
public int EmptyMainMonsterZones;
public int EmptyExtraMonsterZones;
public int EmptySpellTrapZones;
public int LP;
public int NormalSummons;
public int DrawnCards;
public string LastEvent;
public List<Card> CardPool = new List<Card>();
public List<string> ScenarioSteps = new List<string>();
public void Init(string name,string location,string position = "-")
{
Card c = new Card(name);
if(location == "Main Monster Zone")
{
c.SetLocation(location);
EmptyMainMonsterZones--;
}
else if (location == "Extra Monster Zone")
{
c.SetLocation(location);
EmptyExtraMonsterZones--;
}
else
{
c.SetLocation(location);
c.SetPosition(position);
c.SetCard_ID(Card_ID);
Card_ID++;
CardPool.Add(c);
}
}
public void PrintScenarioSteps()
{
for(int i=0;i<ScenarioSteps.Count;i++)
{
Console.WriteLine(ScenarioSteps[i]);
}
}
public void Print()
{
for(int i=0;i<CardPool.Count;i++)
{
if(!CardPool[i].IsLocation("No Location"))
{
Console.WriteLine("{0} ({1}) is in the {2}", CardPool[i].getName(), CardPool[i].getLevel(), CardPool[i].getLocation());
}
}
}
// Checks
bool IsCanBeNormalSummoned(Card c)
{
if (c.IsLevelBelow(4) && c.IsLocation("Hand") && EmptyMainMonsterZones > 0 && NormalSummons > 0) return true;
if (c.IsException("Normal Summon without Tribute") && c.IsLocation("Hand") && EmptyMainMonsterZones > 0 && NormalSummons > 0) return true;
return false;
}
// Operations
public bool NormalSummon(ref Card c)
{
if(IsCanBeNormalSummoned(c))
{
c.SetPreviousLocation(c.getLocation());
c.NormalSummoned = true;
c.SetLocation("Main Monster Zone");
EmptyMainMonsterZones--;
NormalSummons--;
LastEvent = "Normal Summon";
if(!c.Negated)
{
if(c.IsName("Fusilier Dragon, the Dual-Mode Beast"))
{
c.SetAttack(c.getAttack()/2);
c.SetDefense(c.getDefense()/2);
}
}
return true;
}
return false;
}
}
class Program
{
static List<Game> Matrix = new List<Game>();
static void Main(string[] args)
{
Game Duel = new Game();
Duel.Init("Level Eater", "Hand");
Duel.Init("Junk Forward", "Hand");
Duel.Init("Fusilier Dragon, the Dual-Mode Beast","Hand");
Matrix.Add(Duel);
Game g1 = new Game(Matrix[0]);
Console.WriteLine("g1:");
g1.Print();
Console.WriteLine();
Console.WriteLine("Matrix[0]:");
Matrix[0].Print();
Console.WriteLine();
Card c1 = g1.CardPool[0];
if (g1.NormalSummon(ref c1))
{
string s = "Normal Summon " + g1.CardPool[0].getName() + ".";
g1.ScenarioSteps.Add(s);
Console.WriteLine("After Normal Summon:");
Console.WriteLine("g1:");
g1.Print(); // Pointing to the same address!!!
Console.WriteLine();
Console.WriteLine("Matrix[0]:");
Matrix[0].Print(); // This changes, too!!!
Console.WriteLine();
Matrix.Add(g1);
}
g1 = new Game(Matrix[0]);
if (Matrix[0].CardPool[0].IsLocation("Main Monster Zone")) Console.WriteLine("Yes, but I shouldn't be changed!");
if (g1.CardPool[0].IsLocation("Main Monster Zone")) Console.WriteLine("Yes!");
Card c2 = g1.CardPool[1];
if (g1.NormalSummon(ref c2))
{
string s = "Normal Summon " + g1.CardPool[1].getName() + ".";
g1.ScenarioSteps.Add(s);
g1.Print();
Console.WriteLine();
g1.CardPool[0].Print();
Console.WriteLine();
Matrix.Add(g1);
}
g1 = new Game(Matrix[0]);
Card c3 = g1.CardPool[2];
if (g1.NormalSummon(ref c3))
{
string s = "Normal Summon " + g1.CardPool[2].getName() + ".";
g1.ScenarioSteps.Add(s);
g1.Print();
Console.WriteLine();
Matrix.Add(g1);
}
Console.WriteLine("Matrix Count: " + Matrix.Count);
Console.ReadKey();
}
}
类游戏
{
公共游戏()
{
卡ID=1;
空位面积=5;
EmptyExtraMonsterZones=1;
空培根=5;
LP=8000;
正常值=1;
DrawnCards=0;
LastEvent=“”;
CardPool=新列表();
ScenarioSteps=新列表();
}
公共游戏(其他游戏)
{
Card_ID=other.Card_ID;
EmptyMainMonsterZones=其他。EmptyMainMonsterZones;
EmptyExtraMonsterZones=other.EmptyExtraMonsterZones;
EmptySpellTrapZones=other.EmptySpellTrapZones;
LP=其他.LP;
normal传票=其他。normal传票;
DrawnCards=其他。DrawnCards;
LastEvent=other.LastEvent;
//CardPool=新列表(other.CardPool);
CardPool=新列表();
foreach(其他卡池中的卡c)
{
增加(c);
}
//ScenarioSteps=新列表(其他.ScenarioSteps);
ScenarioSteps=新列表();
foreach(其他.scenario步骤中的字符串s)
{
场景步骤。添加;
}
}
公共对象克隆()
{
返回此.MemberwiseClone();
}
智能卡;
公共int空置区;
公共int EmptyExtraMonsterZones;
公共内特空佩利兹;
公共int LP;
公开传唤;
公共int DrawnCards;
公共事件;
public List CardPool=新列表();
公共列表场景步骤=新建列表();
public void Init(字符串名称、字符串位置、字符串位置=“-”)
{
卡c=新卡(名称);
如果(位置=“主怪物区域”)
{
c、 设置位置(位置);
空区--;
}
否则如果(位置=“额外怪物区域”)
{
c、 设置位置(位置);
清空附加区--;
}
其他的
{
c、 设置位置(位置);
c、 设置位置(位置);
c、 设置卡号(卡号);
卡迪德++;
增加(c);
}
}
public void PrintScenarioSteps()
{
for(inti=0;i0)返回true;
如果(c.IsException(“无贡物的普通召唤”)&&c.IsLocation(“手牌”)&&EmptyMainMonsterZones>0&&NormalNotification>0)返回true;
返回false;
}
//操作
公众传票(参考卡c)
{
如果(IsCanBeNormalSummoned(c))
{
c、 SetPreviousLocation(c.getLocation());
c、 正常召唤=真;
c、 设置位置(“主要怪物区域”);
空区--;
正常传票--;
LastEvent=“正常召唤”;
如果(!c.否定)
{
if(c.IsName(“Fussiler Dragon,双模式野兽”))
{
c、 SetAttack(c.getAttack()/2);
c、 SetDefense(c.getDefense()/2);
}
}
返回true;
}
返回false;
}
}
班级计划
{
静态列表矩阵=新列表();
静态void Main(字符串[]参数)
{
游戏决斗=新游戏();
决斗初始(“水平食客”,“手”);
决斗初始(“垃圾前进”,“手”);
决斗初始(“火龙,双模野兽”,“手”);
矩阵。添加(决斗);
游戏g1=新游戏(矩阵[0]);
控制台写入线(“g1:”);
g1.Print();
Console.WriteLine();
Console.WriteLine(“矩阵[0]:”);
矩阵[0]。打印();
Console.WriteLine();
卡c1=g1.卡池[0];
如果(g1.正常召唤(参考c1))
{
字符串s=“普通召唤”+g1.CardPool[0].getName()+”;
g1.场景步骤。添加;
控制台。书写线(“正常召唤后:”);
控制台写入线(“g1:”);
g1.Print();//指向同一地址!!!
Console.WriteLine();
Console.WriteLine(“矩阵[0]:”);
矩阵[0].Print();//这也会改变!!!
Console.WriteLine();
矩阵。添加(g1);
}
g1=新游戏(矩阵[0]);
if(矩阵[0].CardPool[0].IsLocation(“主怪物区域”))Console.WriteLine(“是的,但我不应该被改变!”);
if(g1.CardPool[0].IsLocation(“主怪物区域”))Console.WriteLine(“Yes!”);
卡c2=g1.卡池[1];
如果(g1.正常召唤(参考c2))
{
字符串s=“普通召唤”+g1.CardPool[1].getName()+”;
g1.场景步骤。添加;
g1.Print();
Console.WriteLine();
g1.CardPool[0].Print();
Console.WriteLine();
矩阵。添加(g1);
}
g1=新游戏(矩阵[0]);
卡c3=g1.卡池[2];
如果(g1.正常召唤(参考c3))
{
字符串s=“普通召唤”+g1.CardPool[2].getName()+”;
g1.场景步骤。添加;
g1.Print();
Console.WriteLine();
矩阵。添加(g1);
}
Console.WriteLine(“矩阵计数:+Matrix.Count”);
Console.ReadKey();
}
}
我建议使用一种方法来复制对象,而不是使用对另一个也会更新的对象的引用。您可以将此方法添加到可以为任何游戏对象调用的游戏类中
序列化对象会将其转换为字符串,然后反序列化将其更改回新对象(无需任何引用)
public Game Clone(Game other)
{
return JsonConvert.DeserializeObject<Game>(JsonConvert.SerializeObject(other));
}
Game g1 = new Game().Clone(Matrix[0]);
Game g1 = JsonConvert.DeserializeObject<Game>(JsonConvert.SerializeObject(Matrix[0]);
public object Clone()
{
return this.MemberwiseClone();
}
Game g1 = new Game((Game)Matrix[0].Clone());
static void Main(string[] args)
{
Game Duel = new Game();
Duel.Init("Level Eater", "Hand");
Duel.Init("Junk Forward", "Hand");
Duel.Init("Fusilier Dragon, the Dual-Mode Beast", "Hand");
Matrix.Add(Duel);
Game g1 = new Game((Game)Matrix[0].Clone());
Console.WriteLine("g1:");
g1.Print();
Console.WriteLine();
Console.WriteLine("Matrix[0]:");
Matrix[0].Print();
Console.WriteLine();
Card c1 = g1.CardPool[0];
if (g1.NormalSummon(ref c1))
{
string s = "Normal Summon " + g1.CardPool[0].getName() + ".";
g1.ScenarioSteps.Add("dsqdqdqdq");
Console.WriteLine("After Normal Summon:");
Console.WriteLine("g1:");
g1.Print(); // Pointing to the same address!!!
Console.WriteLine();
Console.WriteLine("Matrix[0]:");
Matrix[0].Print(); // This changes, too!!!
Console.WriteLine();
Matrix.Add(g1);
}
g1 = new Game((Game)Matrix[0].Clone());
if (Matrix[0].CardPool[0].IsLocation("Main Monster Zone")) Console.WriteLine("Yes, but I shouldn't be changed!");
if (g1.CardPool[0].IsLocation("Main Monster Zone")) Console.WriteLine("Yes!");
Card c2 = g1.CardPool[1];
if (g1.NormalSummon(ref c2))
{
string s = "Normal Summon " + g1.CardPool[1].getName() + ".";
g1.ScenarioSteps.Add(s);
g1.Print();
Console.WriteLine();
g1.CardPool[0].Print();
Console.WriteLine();
Matrix.Add(g1);
}
g1 = new Game((Game)Matrix[0].Clone());
Card c3 = g1.CardPool[2];
if (g1.NormalSummon(ref c3))
{
string s = "Normal Summon " + g1.CardPool[2].getName() + ".";
g1.ScenarioSteps.Add(s);
g1.Print();
Console.WriteLine();
Matrix.Add(g1);
}
Console.WriteLine("Matrix Count: " + Matrix.Count);
Console.ReadKey();
}
public class Game : ICloneable
{
public Game()
{
Card_ID = 1;
EmptyMainMonsterZones = 5;
EmptyExtraMonsterZones = 1;
EmptySpellTrapZones = 5;
LP = 8000;
NormalSummons = 1;
DrawnCards = 0;
LastEvent = "";
CardPool = new List<Card>();
ScenarioSteps = new List<string>();
}
public Game(Game other)
{
Card_ID = other.Card_ID;
EmptyMainMonsterZones = other.EmptyMainMonsterZones;
EmptyExtraMonsterZones = other.EmptyExtraMonsterZones;
EmptySpellTrapZones = other.EmptySpellTrapZones;
LP = other.LP;
NormalSummons = other.NormalSummons;
DrawnCards = other.DrawnCards;
LastEvent = other.LastEvent;
//CardPool = new List<Card>(other.CardPool);
CardPool = new List<Card>();
foreach (Card c in other.CardPool)
{
CardPool.Add(c);
}
//ScenarioSteps = new List<string>(other.ScenarioSteps);
ScenarioSteps = new List<string>();
foreach (string s in other.ScenarioSteps)
{
ScenarioSteps.Add(s);
}
}
int Card_ID;
public int EmptyMainMonsterZones;
public int EmptyExtraMonsterZones;
public int EmptySpellTrapZones;
public int LP;
public int NormalSummons;
public int DrawnCards;
public string LastEvent;
public List<Card> CardPool = new List<Card>();
public List<string> ScenarioSteps = new List<string>();
public void Init(string name, string location, string position = "-")
{
Card c = new Card(name);
if (location == "Main Monster Zone")
{
c.SetLocation(location);
EmptyMainMonsterZones--;
}
else if (location == "Extra Monster Zone")
{
c.SetLocation(location);
EmptyExtraMonsterZones--;
}
else
{
c.SetLocation(location);
c.SetPosition(position);
c.SetCard_ID(Card_ID);
Card_ID++;
CardPool.Add(c);
}
}
public void PrintScenarioSteps()
{
for (int i = 0; i < ScenarioSteps.Count; i++)
{
Console.WriteLine(ScenarioSteps[i]);
}
}
public void Print()
{
for (int i = 0; i < CardPool.Count; i++)
{
if (!CardPool[i].IsLocation("No Location"))
{
Console.WriteLine("{0} ({1}) is in the {2}", CardPool[i].getName(), CardPool[i].getLevel(), CardPool[i].getLocation());
}
}
}
// Checks
bool IsCanBeNormalSummoned(Card c)
{
if (c.IsLevelBelow(4) && c.IsLocation("Hand") && EmptyMainMonsterZones > 0 && NormalSummons > 0) return true;
if (c.IsException("Normal Summon without Tribute") && c.IsLocation("Hand") && EmptyMainMonsterZones > 0 && NormalSummons > 0) return true;
return false;
}
// Operations
public bool NormalSummon(ref Card c)
{
if (IsCanBeNormalSummoned(c))
{
c.SetPreviousLocation(c.getLocation());
c.NormalSummoned = true;
c.SetLocation("Main Monster Zone");
EmptyMainMonsterZones--;
NormalSummons--;
LastEvent = "Normal Summon";
if (!c.Negated)
{
if (c.IsName("Fusilier Dragon, the Dual-Mode Beast"))
{
c.SetAttack(c.getAttack() / 2);
c.SetDefense(c.getDefense() / 2);
}
}
return true;
}
return false;
}
public object Clone()
{
return this.MemberwiseClone();
}
}