1

I'm receiving an InvalidCastException when running my code in Xamarin iOS. This doesn't happen for .NET or Android - only for iOS. Here's the exception details:

at Microsoft.Scripting.Interpreter.EqualInstruction+EqualInt64.DoCalculate (System.Object l, System.Object r) [0x00000] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs:84 at Microsoft.Scripting.Interpreter.ComparisonInstruction.Calculate (System.Object l, System.Object r) [0x00015] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ComparisonInstruction.cs:44 at Microsoft.Scripting.Interpreter.ArithmeticInstruction.Run (Microsoft.Scripting.Interpreter.InterpretedFrame frame) [0x00020] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ArithmeticInstruction.cs:45 at Microsoft.Scripting.Interpreter.Interpreter.Run (Microsoft.Scripting.Interpreter.InterpretedFrame frame) [0x0001b] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Interpreter.cs:126

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in /Users/builder/data/lanes/3426/6c3fee4d/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 at XamarinFormsPortable.Models.TweetingViewModel+d__4.MoveNext () [0x00328] in C:\Projects\LinqToTwitter\Samples\Xamarin4\XamarinFormsPortable\XamarinFormsPortable\XamarinFormsPortable\Models\TweetingViewModel.cs:54

The code that causes the problem is a LINQ to Twitter query:

            var ctx = new TwitterContext(auth);
            ulong InitialTweetId = 1;
            int MaximumTweetsToRetrieve = 20;

            var tweetsQuery = from tweet in ctx.Status
                              where tweet.Type == StatusType.User &&
                              tweet.ScreenName == "reinoso_alvaro" &&
                              tweet.Text.Contains("#buenosdias") &&
                              tweet.IncludeRetweets == false &&
                              tweet.TrimUser == true &&
                              tweet.ExcludeReplies == true &&
                              tweet.SinceID == InitialTweetId &&
                              tweet.Count == MaximumTweetsToRetrieve
                              select tweet;
            var tweetList = await tweetsQuery.ToListAsync();

The condition that causes the problem is SinceID, which is ulong. However, you can see from the stack trace that the last method is EqualInt64, which is long. I looked for every place where I worked with SinceID and they are all ulong. The exception occurs on the last line: awaiting tweetsQuery.ToListAsync()

The implementation of ToListAsync is:

    public static async Task<List<T>> ToListAsync<T>(this IQueryable<T> query)
    {
        var provider = query.Provider as TwitterQueryProvider;

        IEnumerable<T> results = (IEnumerable<T>)await provider.ExecuteAsync<IEnumerable<T>>(query.Expression).ConfigureAwait(false);

        return results.ToList();
    }

ExecuteAsync runs and returns results. Then the exception occurs when materializing via results.ToList().

This is only happening on iOS.

jrbedard
  • 3,662
  • 5
  • 30
  • 34
Joe Mayo
  • 7,501
  • 7
  • 41
  • 60

1 Answers1

0

A possible workaround is to cast the Status.SinceID property in the expression:

[...]
&& (long)tweet.SinceID == sinceStatusId // sinceStatusId is a long
[...]

Interesting point, Mono's Interpreter object comparison instructions for unsigned integers are assigned instances of their signed counterparts (https://github.com/mono/mono/blob/mono-4.8.0-branch/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs , line 155 to 157):

case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new EqualInt16());
case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new EqualInt32());
case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new EqualInt64());

Not sure if this is intentional or not.

  • While the cast to long might work today, SinceID is intentionally ulong to handle the potential for the size to grow. Also, signed isn't semantically correct in this scenario. That said, this would be a temporary work-around. – Joe Mayo Feb 08 '17 at 18:38