[英]Deep cloning a deep object in C# (very deep)
我正在用Antlr4和C#编写玩具语言。 现在,我正在尝试编写一个类系统。 但是一个大问题使我的工作停了下来。 当我尝试克隆用户创建的类的实例时,其中的所有内容均引用原始类。 我的“班级”代码在这里
[Serializable]
public class Class : ICloneable
{
public string ID;
public ClassDef ClassContent = new ClassDef();
public Helper ErrorHandler = new Helper();
public Class()
{
ID = "";
}
public Class(string id)
{
ID = id;
}
public void Create(MainGrammarParser.ClassblockContext block)
{
ClassDef def = new ClassDef();
def.Visit(block);
ClassContent = def;
}
public object Clone()
{
Class clone = new Class(ID);
clone.ClassContent = ClassContent.DeepClone();
return clone;
}
}
和“ ClassDef”的代码
public class ClassDef : SuperClass, ICloneable
{
public override bool VisitClassStatFunctionDef([NotNull] MainGrammarParser.ClassStatFunctionDefContext context)
{
FunctionDefParser fd = GetFunctionDefParser();
fd.Visit(context.functiondef());
return true;
}
public override bool VisitClassStatElementDef([NotNull] MainGrammarParser.ClassStatElementDefContext context)
{
string id = context.classelem().ID().GetText();
if (IsVarExists(id) || IsFunctionExists(id) || IsClassExists(id))
{
ErrorHandler.DuplicateError("[ELEMENT] '" + id + "'");
}
ExpParser exp = GetExpParser();
VarObject v = new VarObject(id);
v.Value = exp.Visit(context.classelem().exp());
Variables.Add(v);
return true;
}
}
和超类代码
public class SuperClass : MainGrammarBaseVisitor<bool>, ICloneable
{
public VarCollection Variables = new VarCollection();
public FunctionCollection Functions = new FunctionCollection();
public ClassCollection Classes = new ClassCollection();
public Helper ErrorHandler = new Helper();
public VarObject GetVar(string id)
{
if (!IsVarExists(id))
{
ErrorHandler.NotFoundError("[DEFINITION] '" + id + "'");
}
return Variables.Find(id);
}
public Function GetFunction(string id)
{
if (!IsFunctionExists(id))
{
ErrorHandler.NotFoundError("[METHOD] '" + id + "'");
}
return Functions.Find(id);
}
public Class GetClass(string id)
{
if (!IsClassExists(id))
{
ErrorHandler.NotFoundError("[CLASS] '" + id + "'");
}
return Classes.Find(id);
}
public bool IsVarExists(string id)
{
if (!Variables.Contains(id)) { return false; }
return true;
}
public bool IsFunctionExists(string id)
{
if (!Functions.Contains(id)) { return false; }
return true;
}
public bool IsClassExists(string id)
{
if (!Classes.Contains(id)) { return false; }
return true;
}
public ExpParser GetExpParser()
{
ExpParser output = new ExpParser();
output.Parent = this;
return output;
}
public EqualityParser GetEqualityParser()
{
EqualityParser output = new EqualityParser();
output.Parent = this;
return output;
}
public FunctionDefParser GetFunctionDefParser()
{
FunctionDefParser output = new FunctionDefParser();
output.Parent = this;
return output;
}
public IfParser GetIfParser()
{
IfParser output = new IfParser();
output.Parent = this;
return output;
}
public object Clone()
{
SuperClass output = new SuperClass();
output.Variables = Variables.DeepClone();
output.Functions = Functions.DeepClone();
output.Classes = Classes.DeepClone();
return output;
}
public SuperClass()
{ }
}
我自己编写了VarCollection,FunctionCollection和ClassCollection,它们只是具有find和exist方法的列表。 当我用我的语言尝试这样的代码时
class abc
{
this a = "a"
this b = "b"
this c = "c"
void abc(){}
}
newabc1 = new abc()
newabc1.a = 10
new1a = newabc1.a
newabc2 = new abc()
new2a = newabc2.a
“ new1a”和new2a都设置为10。我尝试了大多数技术,包括:反射,序列化,JsonSerialization,ICloneable,MemberWiseClone ...
在序列化中,我需要将[Serializable]应用于每个类,包括Antlr4自动生成的类。 因此,当我更新语法时,我需要再次放置它们。
在Json序列化(NewtonJson)中,序列化进入无限循环(Serializator警告我有关自引用循环,并且我禁用了循环错误)。
反射,IClonable,MemberWiseClone,这些都无法正常工作。 他们在内存中引用相同的地址,所以我得到相同的错误。
有什么帮助吗?
您可以使用序列化来深克隆对象,但请记住,您必须进行以下设置:
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
到序列化程序,以防止进入无限循环。 如果您正在使用Newtonsoft,但是许多序列化程序都存在类似的ReferenceLoopHandling设置选项。
我解决了这个问题,但实际上不是:)我将字典实例用作类(例如在JavaScript中)。 当与Antlr一起使用时,在NewtonJson中创建序列化的对象是无效的,因为巨大的源代码会使序列化非常慢(大约2-3秒)。 这是我解决问题的方法。 有谁知道解析器生成器或创建语言的出色教程,这是我标记此答案之前的最后一个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.