The code below is throwing System.StackOverflowException
in VS2015 Update 3 (Resharper 2016, Windows 10 x64, .NET 4.5). IMO, it is due to the cyclic initialization in the static constructors of City
-> Authority
-> Country
-> City
. Strange enough, it is working with VS2015 Update 2.
This is the exception that I got in Visual Studio:
System.StackOverflowException {"Exception of type 'System.StackOverflowException' was thrown."}
Data : {System.Collections.ListDictionaryInternal}
Count: 0
IsFixedSize: false
IsReadOnly: false
IsSynchronized: false
Keys : {System.Collections.ListDictionaryInternal.NodeKeyValueCollection}
[]
SyncRoot : {object}
Values: {System.Collections.ListDictionaryInternal.NodeKeyValueCollection}
[]
HelpLink: null
HResult: -2147023895
InnerException: null
Message: Exception of type 'System.StackOverflowException' was thrown.
Source: null
StackTrace: null
TargetSite: null
I wonder why it works with Update 2 but not with Update 3, and more importantly, what can I do to fix it ? This the test code :
public class Program
{
public static void Main(string []args)
{
var p1 = PeopleTestData.GetByID(1);
Console.WriteLine(p1.Name);
}
}
Here are the initialization using Lazy
and static constructors:
public static class PeopleTestData
{
public static readonly Lazy<List<Person>> People;
static PeopleTestData()
{
People = new Lazy<List<Person>>(() => new List<Person>
{
new Person {Name = "Person1", City = CityTestData.GetByID(1), ID = 1},
new Person {Name = "Person2", City = CityTestData.GetByID(2), ID = 2},
//~6000 records
});
}
public static Person GetByID(int personID)
{
return People.Value.Single(p => p.ID == personID);
}
}
public static class CityTestData
{
public static readonly Lazy<List<City>> Cities;
static CityTestData()
{
Cities = new Lazy<List<City>>(() => new List<City>
{
new City {Name = "City1", Authority = AuthorityTestData.GetByID(1), Country = CountryTestData.GetByID(1), ID = 1},
new City {Name = "City2", Authority = AuthorityTestData.GetByID(2), Country = CountryTestData.GetByID(2), ID = 2},
//~5000 records
});
}
public static City GetByID(int cityID)
{
return Cities.Value.Single(p => p.ID == cityID);
}
}
public static class CountryTestData
{
public static readonly Lazy<List<Country>> Countries;
static CountryTestData()
{
Countries = new Lazy<List<Country>>(() => new List<Country>
{
new Country {Name = "Country1", Cities = CityTestData.Cities.Value.Where(c=>c.Country.ID == 1).ToList(), ID = 1},
new Country {Name = "Country2", Cities = CityTestData.Cities.Value.Where(c=>c.Country.ID == 2).ToList(), ID = 2},
//~200 records
});
}
public static Country GetByID(int countryID)
{
return Countries.Value.Single(p => p.ID == countryID);
}
}
public static class AuthorityTestData
{
public static readonly Lazy<List<Authority>> Authorities;
static AuthorityTestData()
{
Authorities = new Lazy<List<Authority>>(() => new List<Authority>
{
new Authority {Name = "Authority1", Country = CountryTestData.GetByID(1), ID = 1},
new Authority {Name = "Authority2", Country = CountryTestData.GetByID(2), ID = 2},
//~3000 records
});
}
public static Authority GetByID(int authorityID)
{
return Authorities.Value.Single(p => p.ID == authorityID);
}
}
And the domain entity:
public class Person
{
public int ID;
public string Name;
public City City;
}
public class City
{
public int ID;
public string Name;
public Country Country;
public Authority Authority;
}
public class Authority
{
public int ID;
public string Name;
public Country Country;
}
public class Country
{
public int ID;
public string Name;
public List<City> Cities;
}