C# 为什么我的getter会被调用,直到出现堆栈溢出?
我在我的Winforms应用程序中使用了一个通用列表,在整个代码中,我将首先检查底层json文件是否存在,如果存在,将其反序列化,然后访问反序列化的通用列表。我决定最好将代码放在一个地方,因此:C# 为什么我的getter会被调用,直到出现堆栈溢出?,c#,linq,json.net,getter,accessor,C#,Linq,Json.net,Getter,Accessor,我在我的Winforms应用程序中使用了一个通用列表,在整个代码中,我将首先检查底层json文件是否存在,如果存在,将其反序列化,然后访问反序列化的通用列表。我决定最好将代码放在一个地方,因此: public static List<AssignmentHistory> assignmentHistList { get { return GetAssignmentHistoryList(); } } public static List<AssignmentHisto
public static List<AssignmentHistory> assignmentHistList
{
get { return GetAssignmentHistoryList(); }
}
public static List<AssignmentHistory> GetAssignmentHistoryList()
{
if (!System.IO.File.Exists(ASSIGNMENT_HISTORY_FILENAME)) return null;
if (null == assignmentHistList)
{
return DeserializeAssignmentHistFile();
}
return assignmentHistList;
}
public static List<AssignmentHistory> DeserializeAssignmentHistFile()
{
var assignmentHistFile = System.IO.File.ReadAllText(ASSIGNMENT_HISTORY_FILENAME);
var assignmentHistDeserialized = JsonConvert.DeserializeObject<List<AssignmentHistory>>(assignmentHist);
return assignmentHistDeserialized;
}
…但永远不要超出该行,因为GetAssignmentHistoryList会被反复调用,直到出现堆栈溢出。我做错了什么
使现代化
我使用了abto的null合并运算符建议,但为了防止出现空文件的可能性,我还必须修改我的反序列化方法,以便现在:
private static List<AssignmentHistory> DeserializeAssignmentHistFile()
{
List<AssignmentHistory> assignmentHistoryList;
if (!System.IO.File.Exists(ASSIGNMENT_HISTORY_FILENAME))
{
var assignmentFile = System.IO.File.Create(ASSIGNMENT_HISTORY_FILENAME);
assignmentFile.Close();
}
var assignmentHistFile = System.IO.File.ReadAllText(ASSIGNMENT_HISTORY_FILENAME);
var assignmentHistDeserialized = JsonConvert.DeserializeObject<List<AssignmentHistory>>(assignmentHistFile);
if (null != assignmentHistDeserialized) return assignmentHistDeserialized;
assignmentHistoryList = new List<AssignmentHistory>();
return assignmentHistoryList;
}
assignmentHistList属性的getter调用GetAssignmentHistoryList,后者递归调用assignmentHistList属性的getter
goto Label1;
您可能希望将该属性称为AssignmentHistList,并使用大写字母A,符合常见的代码样式实践,并且具有私有静态字段AssignmentHistList。无论如何,属性X和GetX方法的双重性是存在的。堆栈溢出异常通常是由于未正确检测到的递归调用条件而发生的
只有通过观察下面的代码,我们才能推断出它们是一个visious循环调用
assignmentHistList->GetAssignmentHistoryList,用于检查条件null==assignmentHistList,但为了检查此条件,需要再次输入assignmentHistList的递归,然后再次调用GetAssignmentHistoryList。。你可以看到这是怎么回事
public static List<AssignmentHistory> assignmentHistList
{
get { return GetAssignmentHistoryList(); }
}
public static List<AssignmentHistory> GetAssignmentHistoryList()
{
if (!System.IO.File.Exists(ASSIGNMENT_HISTORY_FILENAME)) return null;
if (null == assignmentHistList) << Here is another call to the Getter
// The rest is not important
}
因为您的代码失败的原因已经有了答案,所以我想发布一个可能的代码修复程序:
// this is the backing field for your property
private static List<AssignmentHistory> assignmentHistList;
// it is good practice to name properties starting uppercase
public static List<AssignmentHistory> AssignmentHistList
{
get
{
// return the content of the backing field if is not null
return assignmentHistList ??
// in case the backing field is null,
// assign it a value from your deserialize method
// and than return it
(assignmentHistList = DeserializeAssignmentHistFile());
}
}
private static List<AssignmentHistory> DeserializeAssignmentHistFile()
{
// If the file which should contain your data does not exist (yet) return null,
// the property will retry to set the backing field the next time it is accessed
if (!System.IO.File.Exists(ASSIGNMENT_HISTORY_FILENAME)) return null;
var assignmentHistFile
= System.IO.File.ReadAllText(ASSIGNMENT_HISTORY_FILENAME);
var assignmentHistDeserialized
= JsonConvert.DeserializeObject<List<AssignmentHistory>>(assignmentHist);
return assignmentHistDeserialized;
}
请记住,如果应该从中反序列化的文件不存在,这将引发ArgumentNullException。是否看到assignmentHistList和GetAssignmentHistoryList之间的循环引用?使用调试器逐步调试它,您将看到在这两者之间不断切换。在GetAssignmentHistoryList中,您返回assignmentHistList属性,该属性本身返回GetAssignmentHistoryList的结果。GetAssignmentHistoryList读取属性assignmentHistList,它的get函数调用GetAssignmentHistoryList。如果你用F11一步一步地看代码,这应该是显而易见的。goto的一个罕见的好用法,可能是。@Quetzalcatl我真的很喜欢在过去的20年左右第一次将它用于实际目的:D注到B。Clay Shannon:很可能不是小写赋值HistList getter only属性,您希望为大写的GetAssignment提供一个简单的支持字段…-我的意思是:私有静态列表分配HistList;。另外,我注意到您正试图在GetAssignment中实现延迟初始化…-为此,您需要更改return DeserializeAssignmentHistFile;to assignmentHistList=反序列化AssignmentHistFile;返回赋值历史列表;谢谢你,阿博托;我想给你一笔赏金,但除非这个问题重新开始,否则这是不可能的。。。
public static List<AssignmentHistory> assignmentHistList
{
get { return GetAssignmentHistoryList(); }
}
public static List<AssignmentHistory> GetAssignmentHistoryList()
{
if (!System.IO.File.Exists(ASSIGNMENT_HISTORY_FILENAME)) return null;
if (null == assignmentHistList) << Here is another call to the Getter
// The rest is not important
}
// this is the backing field for your property
private static List<AssignmentHistory> assignmentHistList;
// it is good practice to name properties starting uppercase
public static List<AssignmentHistory> AssignmentHistList
{
get
{
// return the content of the backing field if is not null
return assignmentHistList ??
// in case the backing field is null,
// assign it a value from your deserialize method
// and than return it
(assignmentHistList = DeserializeAssignmentHistFile());
}
}
private static List<AssignmentHistory> DeserializeAssignmentHistFile()
{
// If the file which should contain your data does not exist (yet) return null,
// the property will retry to set the backing field the next time it is accessed
if (!System.IO.File.Exists(ASSIGNMENT_HISTORY_FILENAME)) return null;
var assignmentHistFile
= System.IO.File.ReadAllText(ASSIGNMENT_HISTORY_FILENAME);
var assignmentHistDeserialized
= JsonConvert.DeserializeObject<List<AssignmentHistory>>(assignmentHist);
return assignmentHistDeserialized;
}
AssignmentHistory ah = AYttFMConstsAndUtils.AssignmentHistList
.FirstOrDefault(i => i.WeekOfAssignment == currentWeek && i.TalkType == 1);