Search code examples
.netdatetimevstoencapsulation

Private method as assembly's first method in call stack


The following exception was recorded in the log on a client system.

System.ArgumentOutOfRangeException: Value to add was out of range.
Parameter name: value
  at System.DateTime.Add(Double value, Int32 scale)
  at ButtonPressed()
  at MessageEvent(MessageEventArgs e)

The custom method is fairly simple

Public Sub ButtonPressed
    If mWindows.Count > 0 AndAlso mLastEvent.AddSeconds(1) > Now
        PostMessage(New IntPtr(mHwnd), 1125, UIntPtr.Zero, IntPtr.Zero)
    End If
End Sub

I am having troubles to explain how such a call stack is at all possible since DateTime.Add(Double value, Int32 scale) is a private method and not called by my code.

DateTime.Now is throwing an exception seems to give an explanation for this in multi-threaded environments. But there is no call to DateTime.get_Now on my call stack so is it really the same root cause?


Solution

  • I suspect the JIT has inlined the AddSeconds method, that's all.

    For example, consider this very simple code:

    using System;
    
    class Test
    {
        static void Main()
        {
            var max = DateTime.MaxValue;
            var oops = max.AddSeconds(1);
        }
    }
    

    On my .NET 4.5 machine, that generates a stack trace of:

    Unhandled Exception: System.ArgumentOutOfRangeException:
       The added or subtracted value results in an un-representable DateTime.
    Parameter name: value
       at System.DateTime.AddTicks(Int64 value)
       at Test.Main()
    

    Note the lack of an AddSeconds call. Now it's not the exact same trace as you're seeing, but that may well be due to framework version differences.

    I suggest you log mLastEvent at the start of the method - my guess is that you'll find that's close to DateTime.MaxValue.