static readonly field causes StackOverflowException - c#

In ASP.NET website I have static readonly XGeoPhone provider = new XGeoPhone();. Inside of XGeoPhone class I have static readonly XPhoneInfo[] phoneInfo = new[] { new XPhoneInfo(......), ... 250000 more objects ... }. When I run this on developer machine or real server — it crashes at new XGeoPhone() with StackOverflowException. I do not quite understand it tries to create this giant array on stack, not heap? What is going on?
UPDATE: Simplest version that will crash:
public partial class XGeoPhone
{
public XPhoneInfo GetInfo(long phone)
{
return
phoneInfos.
FirstOrDefault(pi =>
pi.Start <= phone &&
phone <= pi.End);
}
static readonly XPhoneInfo[] phoneInfos = new[]
{
new XPhoneInfo(2000000000, 2099999999, XCountryId.EG, null, null),
new XPhoneInfo(2120000000, 2129999999, XCountryId.MA, null, null),
new XPhoneInfo(2130000000, 2139999999, XCountryId.DZ, null, null),
new XPhoneInfo(2160000000, 2169999999, XCountryId.TN, null, null),
new XPhoneInfo(2180000000, 2189999999, XCountryId.LY, null, null),
.........
}
}
public class XPhoneInfo
{
public XPhoneInfo(long start, long end, XCountryId? country, string region, string provider)
{
this.Start = start;
this.End = end;
this.Country = country;
this.Region = region;
this.Provider = provider;
}
public long Start { get; private set; }
public long End { get; private set; }
public XCountryId? Country { get; private set; }
public string Region { get; private set; }
public string Provider { get; private set; }
}
class Program
{
static readonly XGeoPhone g = new XGeoPhone();
static void Main(string[] args)
{
var v = g.GetInfo(79054567890);
}
}

Okay, I found the workaround — I can create a thread and specify the stack size in a thread’s constructor, like described here. It works. But I decided to move that big array to csv file.

Related

Accessing elements of a list in another class

Lets say I have something like the following.
namespace BurgerMachine
{
public class BaseList{
private static readonly List<Bases> bList = new List<Bases>() //might need to take off readonly
{
new Bases(){ BaseID=1, BaseName="Bun"},
new Bases(){ BaseID=2, BaseName="SeededBun"}
};
public static List<Bases> GetList()
{
return bList;
}
}
public class Bases
{
public int BaseID { get; set; }
public string BaseName { get; set; }
}
}
Now I would like to access the elements of the above list from another class, is this doable with my current setup or do I need to be returning more?
I have seen a few examples of people creating a List and then adding to from another class but not trying to access elements that already exist. If such an example does exist please point me in the right direction.
First time using Lists in this fashion so I'm not quite sure what I am doing. Any help would be great. If more information is needed please ask.
Here are few implementations best way to return list.
With static class
public class BaseListProvider
{
public static readonly Bases Bun = new Bases() { BaseID = 1, BaseName = "Bun" };
public static readonly Bases SeededBun = new Bases() { BaseID = 2, BaseName = "SeededBun" };
public static IEnumerable<Bases> GetList()
{
return new[]
{
Bun,
SeededBun
};
}
}
public class Bases
{
public int BaseID { get; set; }
public string BaseName { get; set; }
}
With interface which can be helpful if you are using dependency injection
public class BaseListProvider : IBaseListProvider
{
public static readonly Bases Bun = new Bases() { BaseID = 1, BaseName = "Bun" };
public static readonly Bases SeededBun = new Bases() { BaseID = 2, BaseName = "SeededBun" };
public IEnumerable<Bases> GetList()
{
return new[]
{
Bun,
SeededBun
};
}
}
public interface IBaseListProvider
{
IEnumerable<Bases> GetList();
}
public class Bases
{
public int BaseID { get; set; }
public string BaseName { get; set; }
}
Well you could just make the list a public member like below and access it from wherever you want
public List<Bases> bList = new List<Bases>()
{
new Bases(){ BaseID=1, BaseName="Bun"},
new Bases(){ BaseID=2, BaseName="SeededBun"}
};
You can access now saying
var blist = new BaseList().bList;
With your current setup (as already commented) why can't you just call the static method saying BaseList.GetList()

C# Static property in non-static class as indicator of main object of this class

I have class Important and some objects of this class created. I want allow user to choose main object of this class. Have a look at code below:
public class Program
{
public static void Main(string[] args)
{
Important imp1 = new Important("Important 1");
Important imp2 = new Important("Important 2");
Important imp3 = new Important("Important 3");
imp2.SetMostImportant();
Console.Write(Important.MostImportant.Name);
}
public class Important
{
public Important(string name)
{
Name = name;
if(MostImportant == null)
SetMostImportant();
}
public string Name { get; private set; }
public static Important MostImportant { get; private set; }
public void SetMostImportant()
{
MostImportant = this;
}
}
}
Is it good solution? If not, please tell me why not.
Before, to achieve this kind of things I just created boolean field named e.g. IsMainObject and, when I wanted to change main object, I iterated through all objects (or group of object) of specific class except element that I want to be main, and changed boolean to false, in my new candidate I simply set flag to true. Example below:
public class Program
{
public static void Main(string[] args)
{
Important imp1 = new Important("Important 1");
Important imp2 = new Important("Important 2");
Important imp3 = new Important("Important 3");
List<Important> list = new List<Important> { imp1, imp2, imp3 };
foreach(var item in list.Where(x => x.Name != "Important 2"))
{
item.SetMostImportant(false);
}
imp2.SetMostImportant(true);
Console.Write(list.FirstOrDefault(x => x.MostImportant == true).Name);
}
public class Important
{
public Important(string name)
{
Name = name;
}
public string Name { get; private set; }
public bool MostImportant { get; private set; }
public void SetMostImportant(bool val)
{
MostImportant = val;
}
}
}
I don't like this solution because:
I don't know if MostImportant is true for more than one objects without iterating.
I need to write extra-code to handle much more cases.
I don't have possibility to always iterate through all instances of specific class (groups not always are enough).
... and much more, but you got the idea.
public static Important MostImportant { get; private set; }
is a fine solution, and much better than
public bool MostImportant { get; private set; }
It's not uncommon to have a static property of the type that it's inside of when implementing "singleton" classes. I've written code that resembles this:
class MyClass
{
public static MyClass Instance { get; private set; }
public MyClass()
{
if (Instance == null)
{
Instance = this;
}
else
{
throw new Exception("MyClass already instantiated.");
}
}
}

How can I log the execution order of tests in xUnit

I have a large test set (5k+) using xUnit.net, and I'm having concurrency problems among tests running in parallel.
xUnit randomizes the execution order of tests, which makes it harder for me to detect the issue.
I'd like to know whether is there a way to log, during test execution, the moment a test starts and the moment it ends.
Note: Using constructor and disposer methods does not cut it, because you cannot know which test is being run on the constructor/disposer.
Note 2: In case it is not obvious, I'm looking for a solution that doesn't involve writing log call in each test.
Thanks,
Well, I managed to do it using the BeforeAfterTestAttribute from xUnit. Then I wrote the utility logger below to output the results to a .csv file.
public class LogTestExecutionAttribute: BeforeAfterTestAttribute
{
public override void Before(MethodInfo methodUnderTest)
{
TestExecutionDataLogger.LogBegin(methodUnderTest);
}
public override void After(MethodInfo methodUnderTest)
{
TestExecutionDataLogger.LogEnd(methodUnderTest);
}
}
public static class TestExecutionDataLogger
{
private static readonly string LogFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "DbCoud", $"UnitTests_{DateTime.UtcNow:yyyy_MM_dd_HH_mm}_D_{AppDomain.CurrentDomain.Id}.csv");
private static int _startedOrder = 0;
private static int _endedOrder = 0;
private static readonly ConcurrentDictionary<string, testExecutionData> testDataDict = new ConcurrentDictionary<string, testExecutionData>();
private static readonly ConcurrentQueue<string> logQueue = new ConcurrentQueue<string>();
public static void LogBegin(MethodInfo testInfo)
{
var name = $"{testInfo.DeclaringType.FullName}.{testInfo.Name}";
var order = Interlocked.Add(ref _startedOrder, 1);
var startedUtc = DateTime.UtcNow;
var data = testDataDict.GetOrAdd(name, new testExecutionData());
data.StartedUtc = startedUtc;
data.StartedOrder = order;
data.TestName = name;
data.Status = "Started";
data.StartThreadId = Thread.CurrentThread.ManagedThreadId;
writeLog(data);
}
public static void LogEnd(MethodInfo testInfo)
{
var name = $"{testInfo.DeclaringType.FullName}.{testInfo.Name}";
var dataEndedUtc = DateTime.UtcNow;
var order = Interlocked.Add(ref _endedOrder, 1);
var data = testDataDict[name];
data.EndedUtc = dataEndedUtc;
data.EndedOrder = order;
data.Status = "Ended";
data.EndThreadId = Thread.CurrentThread.ManagedThreadId;
writeLog(data);
}
private static void writeLog(testExecutionData data)
{
logQueue.Enqueue(data.ToCsvLine());
if (data.EndedOrder == 1)
{
Directory.CreateDirectory(Path.GetDirectoryName(LogFileName));
Task.Run(logWriter);
}
}
private static Task logWriter()
{
while (true)
{
var logs = new List<string>();
string result;
while (logQueue.TryDequeue(out result))
{
logs.Add(result);
}
if (logs.Any())
{
File.AppendAllLines(LogFileName, logs);
}
}
}
private class testExecutionData
{
public int StartedOrder { get; set; }
public int EndedOrder { get; set; }
public DateTime StartedUtc { get; set; }
public DateTime EndedUtc { get; set; }
public string TestName { get; set; }
public string Status { get; set; }
public int StartThreadId { get; set; }
public int EndThreadId { get; set; }
public string ToCsvLine() { return $"{TestName};{Status};{StartedOrder};{EndedOrder};{StartedUtc:o};{EndedUtc:o};{Math.Max(0, ( EndedUtc - StartedUtc ).TotalMilliseconds)};{StartThreadId};{EndThreadId}"; }
}
}
To use this code, add the LogTestExecutionAttribute to the test classes you want to log (or to the base classes ;p).

What data structure is appropriate for this?

Within code I want to do something like this:
item.Stage = Stage.Values.ONE;
Where Stage.Values.ONE represents some predefined Stage:
public class Stage
{
[Key]
public virtual int StageId { get; set; }
public string Name { get; set; }
public TimeSpan Span { get; set; }
}
I'm dealing with EF CodeFirst... and I have a lot of stages to define. I'm not sure if I should store the data in the database, or in the dbContext, or what, but I'm looking for the simplest implementation.
I've tried this:
I've tried the following (defining two constants):
public class Stage
{
[Key]
public virtual int StageId { get; set; }
public string Name { get; set; }
public TimeSpan Span { get; set; }
public static class Values
{
public static readonly Stage ONE = new Stage()
{
StageId = 0,
Name = "ONE",
Span = new TimeSpan(0, 0, 0)
};
public static readonly Stage TWO = new Stage()
{
StageId = 1,
Name = "TWO",
Span = new TimeSpan(0, 0, 10)
};
}
But whenever I create a new instance of an entity that has a Stage, a new Stage is added to the db. I just need a few constant stages.
Use of Stage:
public class Side
{
public Side()
{
Stage = Stage.Values.ONE; // Adds new Stage to DB, when it should be a reference to the one I defined above
}
public virtual Stage Stage { get; set; }
}
It looks a bit like an enum, and I've used a kind of 'extended enum' patter several times before with some success. Because you're refencing these values in code, it may not make sense to store them in the database as well, but it's possible if needed.
The technique is described in detail here: http://lostechies.com/jimmybogard/2008/08/12/enumeration-classes/
Basically, you create a base class which provides a number of services similar to an enum, and then to create your "enumerated class" you inherit from it and provide a bunch of static instances which call the constructor with however many properties you need to have.
To avoid link rot, here is the base class to use (just put the whole class into your project somewhere), and scroll down for your own code.
public abstract class Enumeration : IComparable
{
private readonly int _value;
private readonly string _displayName;
protected Enumeration()
{
}
protected Enumeration(int value, string displayName)
{
_value = value;
_displayName = displayName;
}
public int Value
{
get { return _value; }
}
public string DisplayName
{
get { return _displayName; }
}
public override string ToString()
{
return DisplayName;
}
public static IEnumerable<T> GetAll<T>() where T : Enumeration, new()
{
var type = typeof(T);
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
foreach (var info in fields)
{
var instance = new T();
var locatedValue = info.GetValue(instance) as T;
if (locatedValue != null)
{
yield return locatedValue;
}
}
}
public override bool Equals(object obj)
{
var otherValue = obj as Enumeration;
if (otherValue == null)
{
return false;
}
var typeMatches = GetType().Equals(obj.GetType());
var valueMatches = _value.Equals(otherValue.Value);
return typeMatches && valueMatches;
}
public override int GetHashCode()
{
return _value.GetHashCode();
}
public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue)
{
var absoluteDifference = Math.Abs(firstValue.Value - secondValue.Value);
return absoluteDifference;
}
public static T FromValue<T>(int value) where T : Enumeration, new()
{
var matchingItem = parse<T, int>(value, "value", item => item.Value == value);
return matchingItem;
}
public static T FromDisplayName<T>(string displayName) where T : Enumeration, new()
{
var matchingItem = parse<T, string>(displayName, "display name", item => item.DisplayName == displayName);
return matchingItem;
}
private static T parse<T, K>(K value, string description, Func<T, bool> predicate) where T : Enumeration, new()
{
var matchingItem = GetAll<T>().FirstOrDefault(predicate);
if (matchingItem == null)
{
var message = string.Format("'{0}' is not a valid {1} in {2}", value, description, typeof(T));
throw new ApplicationException(message);
}
return matchingItem;
}
public int CompareTo(object other)
{
return Value.CompareTo(((Enumeration)other).Value);
}
}
And now your code will look something like this:
public class Stage : Enumeration
{
public TimeSpan TimeSpan { get; private set; }
public static readonly Stage One
= new Stage (1, "Stage one", new TimeSpan(5));
public static readonly Stage Two
= new Stage (2, "Stage two", new TimeSpan(10));
public static readonly Stage Three
= new Stage (3, "Stage three", new TimeSpan(15));
private EmployeeType() { }
private EmployeeType(int value, string displayName, TimeSpan span) : base(value, displayName)
{
TimeSpan = span;
}
}
Once you have that set up, you can just store the .Value in the database. I'm afraid I haven't done it in EF, but in nHibernate it's reasonably straight-forward to tell a property to just store the ".Value" of the property, and you can wire it back up when you load the value by having it call:
Stage.FromValue<Stage>(intValue);
Hold the Stage as a property of your entity, use it the way you're doing and add
Ignore(x => x.Stage)
to your mapping. This will ignore this property when mapping to your database.
Edit: I misinterpreted the question.
If you want just the different stages in your database, you should put the stages in their own table with an ID, and refer to that ID trough a relationship. Every entity will hold an additional reference and you'll have to define relationships for them.
Is this what you were looking for?

crash Console Application

This is my problem:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public abstract class EntityMember<T>
{
public T Value { get; set; }
}
public class Int32EntityMember : EntityMember<int?>
{
}
public class StringEntityMember : EntityMember<string>
{
}
public class GuidEntityMember : EntityMember<Guid?>
{
}
public class Entity
{
public GuidEntityMember ApplicationId { get; private set; }
public Int32EntityMember ConnectedCount { get; private set; }
public GuidEntityMember MainApplicationId { get; private set; }
public Int32EntityMember ProcessId { get; private set; }
public StringEntityMember ProcessName { get; private set; }
}
class Program
{
static void Main(string[] args)
{
Entity entity2 = new Entity();
Guid empty = Guid.NewGuid();
Guid applicationId = Guid.NewGuid();
int Id = 10;
string name = "koko";
entity2.MainApplicationId.Value = new Guid?(empty);
entity2.ApplicationId.Value = new Guid?(applicationId);
entity2.ProcessId.Value = new int?(Id);
entity2.ProcessName.Value = name;
entity2.ConnectedCount.Value = 1;
}
}
}
The application has totally blocked on the line:
entity2.MainApplicationId. Value = new Guid? (empty);
Why?
The exception you're receiving is:
Object reference not set to an instance of an object.
This is because entity2.MainApplicationId is null. Your Entity class does not have a constructor to set MainApplicationId to be not null, hence the error you're seeing.
Adding a constructor to your Entity class as shown in the code below results in your code running without error:
public Entity()
{
ApplicationId = new GuidEntityMember();
ConnectedCount = new Int32EntityMember();
MainApplicationId = new GuidEntityMember();
ProcessId = new Int32EntityMember();
ProcessName = new StringEntityMember();
}
Using Auto-Implemented properties does not result in the underlying fields (that are created and managed on your behalf by the compiler) being new'd when the instance is constructed. Thus the two properties that follow are not the same:
public MyClass MyProperty { get; private set; }
private MyClass _myOtherProperty = new MyClass();
public MyClass MyOtherProperty
{
get
{
return _myOtherProperty;
}
set
{
_myOtherProperty = value;
}
}
Try changing the line to a type cast:
entity2.ApplicationId.Value = (Guid?)(applicationId);

Categories