Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - internal static readonly is null on access [closed]

Tags:

c#

I have the following code:

internal class FakeInvitationsRepository : InvitationsRepository
{
    internal readonly static Dictionary<Guid, InvitationDbEntity> Data = new Dictionary<Guid, InvitationDbEntity>()
    {
        { ...

Here's a screen-shot, for what its worth:

Screen shot of real code

It's just some in-memory fake data, 3 items in all. The class lives inside an ASP.NET WebAPI project, not in a test DLL but in the WebAPI DLL for the time being.

An API call comes in and hits a breakpoint in the controller action where it tries to consume this fake data directly, no IoC yet or anything clever.

But the field Data is null. It's causing a null ref exception at runtime.

Screen show showing null

The C# language spec says:

If a static constructor (Section 10.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

What's happening here such that the field is not initialized prior to first-use?

Note: A colleague has quickly sanity checked and is also bemused. Data is only ever set, never nulled by my code (its readonly afterall).

Edit

Here's the callstack of just my code:

System.Diagnostics.StackTrace t = new System.Diagnostics.StackTrace();
{   at Company.Product.WebAPI.Controllers.RenamedController.<GetInvitations>d__14.MoveNext()
   at Company.Product.WebAPI.Controllers.RenamedController.GetInvitations(Guid id)
   at lambda_method(Closure , Object , Object[] )
   at Company.WebAPI.Product.Areas.RouteDebugger.InspectActionInvoker.InvokeActionAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
   at Company.WebAPI.Product.Areas.RouteDebugger.InspectHandler.<>n__FabricatedMethod12(HttpRequestMessage , CancellationToken )
   at Company.WebAPI.Product.Areas.RouteDebugger.InspectHandler.<SendAsync>d__e.MoveNext()
   at Company.WebAPI.Product.Areas.RouteDebugger.InspectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
}
    FrameCount: 84
    frames: {System.Diagnostics.StackFrame[87]}
    m_iMethodsToSkip: 3
    m_iNumOfFrames: 84

Answer

I can't answer because the question was put on hold. Debatable.

Thanks to MStodd. The answer is silly and straight-forward, but somewhat surprising; I don't recall having ever seen this in 11 years of .NET programming.

The Data field was not yet initialized.

Placing a breakpoint in the initializer, the entire block goes red, showed that it was called on the next step.

The NullReferenceException was a red-herring and due to this.Invitations being null.

Of course, I was expecting the field to be initialized by the time that line is stopped at, I just didn't expect it to happen so late, and so assumed the null was causing my runtime exception.

There you go.

like image 769
Luke Puplett Avatar asked Nov 09 '22 09:11

Luke Puplett


1 Answers

From your call stack i can deduce that the Invitations property is evaluated(in the Select body). Being the last one on the call stack i can deduce that the null reference raises due to the fact that Invitations is NULL!). I suppose that Data = NULL is NOT related to the call stack at all! but rather it is a debugger issue.

like image 135
George Lica Avatar answered Nov 14 '22 21:11

George Lica