具有递归集合的 class 的 c# 转换运算符
c# conversion operator for class with recursive collection
我一直在努力让一个演员为一个拥有自己的集合的 class 工作。在用列表中有两个 TypeA 元素的根对象进行测试时,当列表进行隐式转换时...它输入集合中 TypeA 元素的转换代码,因为这是树的顶部,returns TypeAIntermediate 不进入 foreach 循环(完美
- SomeAs 中没有任何内容)。但是当它 returns 转换后的实例时,它似乎从根的转换代码的顶部重新开始,就像什么都没发生一样。
据我所知,这永远不会停止。我重写了这个遵循相同格式的简化版本...希望我没有搞砸。
//These are models used in a .Net 4.5 EF6 Library
public class TypeA
{
public string TypeAStuff;
public TypeB JustOneB;
public List<TypeA> SomeAs;
public static implicit operator TypeAIntermediate(TypeA a)
{
//New up an Intermediate A to return.
TypeAIntermediate aI = new TypeAIntermediate();
//And get ready to do handle the collection... a few ways to do this.
List<TypeAIntermediate> children = new List<TypeAIntermediate>();
//...but this appears to create an infinite loop?
foreach (TypeA item in a.SomeAs)
children.Add(item); //Cast from TypeA to to TypeAIntermediate happens here but will just keeps cycling
aI.TypeAStuff = a.TypeAStuff;
aI.JustOneB = a.JustOneB;
aI.SomeAs = children;
return aI;
}
}
public class TypeB
{
public string TypeBStuff;
public static implicit operator TypeBIntermediate(TypeB b)
{
TypeBIntermediate bI = new TypeBIntermediate();
bI.TypeBStuff = b.TypeBStuff;
return bI;
}
}
//These Intermediate Classes live in a .Net35 Library - Unity cannot use Libraries compiled for later .Net Versions.
public class TypeAIntermediate
{
public string TypeAStuff;
public TypeBIntermediate JustOneB;
public List<TypeAIntermediate> SomeAs;
}
public class TypeBIntermediate
{
public string TypeBStuff;
}
如果您的层次结构中有循环,您可以通过以下方式编写代码以避免堆栈溢出。
public static implicit operator TypeAIntermediate(TypeA a)
{
return Convert(a, new Dictionary<TypeA, TypeAIntermediate>());
}
private static TypeAIntermediate Convert(
Type A a,
Dictionary<TypeA, TypeAIntermediate> lookup)
{
TypeAIntermediate aI;
if(lookup.TryGetValue(a, out aI))
{
return aI;
}
aI = new TypeAintermediate();
lookup.Add(a, aI);
List<TypeAIntermediate> children = new List<TypeAIntermediate>();
foreach (TypeA item in a.SomeAs)
children.Add(Convert(item, lookup));
aI.TypeAStuff = a.TypeAStuff;
aI.JustOneB = a.JustOneB;
aI.SomeAs = children;
return aI;
}
基本上,通过使用字典,您可以确定是否有任何 TypeA
对象已经为它创建了一个 TypeAIntermediate
对象,在这种情况下您不需要再次创建它,只需 return对应的TypeAIntermediate
引用。如果还没有,那么您创建一个新的 TypeAIntermediate
并填充它的集合递归调用 Create
方法,该方法也采用字典。
此外,如果您在不同的分支中两次引用相同的对象,这只会创建一个 TypeAIntermediate
引用,而不是两个。
我一直在努力让一个演员为一个拥有自己的集合的 class 工作。在用列表中有两个 TypeA 元素的根对象进行测试时,当列表进行隐式转换时...它输入集合中 TypeA 元素的转换代码,因为这是树的顶部,returns TypeAIntermediate 不进入 foreach 循环(完美 - SomeAs 中没有任何内容)。但是当它 returns 转换后的实例时,它似乎从根的转换代码的顶部重新开始,就像什么都没发生一样。
据我所知,这永远不会停止。我重写了这个遵循相同格式的简化版本...希望我没有搞砸。
//These are models used in a .Net 4.5 EF6 Library
public class TypeA
{
public string TypeAStuff;
public TypeB JustOneB;
public List<TypeA> SomeAs;
public static implicit operator TypeAIntermediate(TypeA a)
{
//New up an Intermediate A to return.
TypeAIntermediate aI = new TypeAIntermediate();
//And get ready to do handle the collection... a few ways to do this.
List<TypeAIntermediate> children = new List<TypeAIntermediate>();
//...but this appears to create an infinite loop?
foreach (TypeA item in a.SomeAs)
children.Add(item); //Cast from TypeA to to TypeAIntermediate happens here but will just keeps cycling
aI.TypeAStuff = a.TypeAStuff;
aI.JustOneB = a.JustOneB;
aI.SomeAs = children;
return aI;
}
}
public class TypeB
{
public string TypeBStuff;
public static implicit operator TypeBIntermediate(TypeB b)
{
TypeBIntermediate bI = new TypeBIntermediate();
bI.TypeBStuff = b.TypeBStuff;
return bI;
}
}
//These Intermediate Classes live in a .Net35 Library - Unity cannot use Libraries compiled for later .Net Versions.
public class TypeAIntermediate
{
public string TypeAStuff;
public TypeBIntermediate JustOneB;
public List<TypeAIntermediate> SomeAs;
}
public class TypeBIntermediate
{
public string TypeBStuff;
}
如果您的层次结构中有循环,您可以通过以下方式编写代码以避免堆栈溢出。
public static implicit operator TypeAIntermediate(TypeA a)
{
return Convert(a, new Dictionary<TypeA, TypeAIntermediate>());
}
private static TypeAIntermediate Convert(
Type A a,
Dictionary<TypeA, TypeAIntermediate> lookup)
{
TypeAIntermediate aI;
if(lookup.TryGetValue(a, out aI))
{
return aI;
}
aI = new TypeAintermediate();
lookup.Add(a, aI);
List<TypeAIntermediate> children = new List<TypeAIntermediate>();
foreach (TypeA item in a.SomeAs)
children.Add(Convert(item, lookup));
aI.TypeAStuff = a.TypeAStuff;
aI.JustOneB = a.JustOneB;
aI.SomeAs = children;
return aI;
}
基本上,通过使用字典,您可以确定是否有任何 TypeA
对象已经为它创建了一个 TypeAIntermediate
对象,在这种情况下您不需要再次创建它,只需 return对应的TypeAIntermediate
引用。如果还没有,那么您创建一个新的 TypeAIntermediate
并填充它的集合递归调用 Create
方法,该方法也采用字典。
此外,如果您在不同的分支中两次引用相同的对象,这只会创建一个 TypeAIntermediate
引用,而不是两个。