我在Winforms应用程序中使用泛型列表,并且在整个过程中都有代码,我将首先检查基础(json)文件是否存在,如果存在,则对其进行反序列化,然后访问反序列化的泛型列表。我决定最好将该代码放在一个地方,因此这样做:
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;
}
然后我这样称呼它:
AssignmentHistory ah =
AYttFMConstsAndUtils.assignmentHistList.FirstOrDefault(
i => i.WeekOfAssignment == currentWeek && i.TalkType == 1);
。但永远不要超出这一行,因为 GetAssignmentHistoryList() 会被一遍又一遍地调用,直到出现堆栈溢出。我在这里做错了什么?
更新
我使用了 abto 的空合并运算符建议,但为了防止空文件的可能性,我还必须修改我的反序列化方法,以便现在:
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;
}
因为已经有答案为什么你的代码失败,我想发布一个可能的代码修复:
// 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);
请记住,如果应从中反序列化的文件不存在,这将引发ArgumentNullException
。
Label1:
assignmentHistList
属性的 getter 调用GetAssignmentHistoryList()
,assignmentHistList
属性的 getter 递归调用。
goto Label1;
您可能希望使用大写A
调用该属性AssignmentHistList
,与常见的代码样式做法保持一致,并具有私有静态字段assignmentHistList
。无论如何,属性X
和GetX()
方法存在的双重性是奇怪的。
堆栈溢出异常通常是由于未正确检测到递归调用条件而发生的。
只有观察下面的代码,我们才能推断出存在一个恶性循环调用。
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
}