Fsharp: F# throwing System.NullReferenceException out of nowhere.

Created on 1 Mar 2019  路  17Comments  路  Source: dotnet/fsharp

VSF_TYPE_MARKDOWNAfter updating Visual Studio, I run my F# App and it is throwing System.NullReferenceException on the type definition, out of nowhere.

See screenshot

_This issue has been moved from https://developercommunity.visualstudio.com/content/problem/472004/f-throwing-systemnullreferenceexception-out-of-now.html
VSTS ticketId: 803507_
_These are the original issue comments:_

Tony Henrique on 2/27/2019, 05:30 PM (38 hours ago):

Screenshot

Tony Henrique on 2/27/2019, 05:52 PM (38 hours ago):

This is what I have on the Call Stack:

ClassLibrary1.dll!Entidades.Pedido.Equals(object obj) Line 70 F#

Visual Studio Feedback System on 2/27/2019, 06:26 PM (37 hours ago):

We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.

_These are the original issue solutions:_
(no solutions)

Most helpful comment

Maybe this is related to the generic code?

let constructedType = typedefof<Pedido>
let x = Activator.CreateInstance(constructedType)

All 17 comments

Image that won't transfer over:
image

The Code that causes that is this:

private void Button_Click(object sender, RoutedEventArgs e)
{
    // uses the F# library from C#
    var pedido = API.Actions.PegaFormPedido(Guid.Parse("4644cf33-06af-44d7-907b-085c2a9b65a3"));// API.Actions.NovoPedido();

    // Binds the returned F# object to WPF UI
    this.DataContext = pedido;
}

Here is the Call Stack

    ClassLibrary1.dll!Entidades.Pedido.Equals(Entidades.Pedido obj) F#
    ClassLibrary1.dll!Entidades.Pedido.Equals(object obj) Line 70   F#
    mscorlib.dll!object.Equals(object objA, object objB)    Unknown
    PresentationFramework.dll!System.Windows.Data.BindingExpression.OnDataContextChanged(System.Windows.DependencyObject contextElement)    Unknown
    PresentationFramework.dll!System.Windows.Data.BindingExpression.HandlePropertyInvalidation(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs args)   Unknown
    PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.OnPropertyInvalidation(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs args)   Unknown
    PresentationFramework.dll!System.Windows.Data.BindingExpression.OnPropertyInvalidation(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs args)   Unknown
    WindowsBase.dll!System.Windows.DependentList.InvalidateDependents(System.Windows.DependencyObject source, System.Windows.DependencyPropertyChangedEventArgs sourceArgs) Unknown
    WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args)    Unknown
    WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) Unknown
    PresentationFramework.dll!System.Windows.TreeWalkHelper.OnInheritablePropertyChanged(System.Windows.DependencyObject d, System.Windows.InheritablePropertyChangeInfo info, bool visitedViaVisualTree)   Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>._VisitNode(System.Windows.DependencyObject d, bool visitedViaVisualTree)   Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.VisitNode(System.Windows.FrameworkElement fe, bool visitedViaVisualTree)   Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.VisitNode(System.Windows.DependencyObject d, bool visitedViaVisualTree)    Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.WalkLogicalChildren(System.Windows.FrameworkElement feParent, System.Windows.FrameworkContentElement fceParent, System.Collections.IEnumerator logicalChildren)    Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.WalkFrameworkElementLogicalThenVisualChildren(System.Windows.FrameworkElement feParent, bool hasLogicalChildren)   Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.IterateChildren(System.Windows.DependencyObject d) Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>._VisitNode(System.Windows.DependencyObject d, bool visitedViaVisualTree)   Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.VisitNode(System.Windows.FrameworkElement fe, bool visitedViaVisualTree)   Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.VisitNode(System.Windows.DependencyObject d, bool visitedViaVisualTree)    Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.WalkLogicalChildren(System.Windows.FrameworkElement feParent, System.Windows.FrameworkContentElement fceParent, System.Collections.IEnumerator logicalChildren)    Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.WalkFrameworkElementLogicalThenVisualChildren(System.Windows.FrameworkElement feParent, bool hasLogicalChildren)   Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.IterateChildren(System.Windows.DependencyObject d) Unknown
    PresentationFramework.dll!System.Windows.DescendentsWalker<System.Windows.InheritablePropertyChangeInfo>.StartWalk(System.Windows.DependencyObject startNode, bool skipStartNode)   Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e)    Unknown
    WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args)    Unknown
    WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) Unknown
    WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal)    Unknown
    WindowsBase.dll!System.Windows.DependencyObject.SetValue(System.Windows.DependencyProperty dp, object value)    Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.DataContext.set(object value) Unknown
    WpfApp1.exe!WpfApp1.MainWindow.Button_Click(object sender, System.Windows.RoutedEventArgs e) Line 36    C#
    PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
    PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)    Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args)   Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e)  Unknown
    PresentationFramework.dll!System.Windows.Controls.Primitives.ButtonBase.OnClick()   Unknown
    PresentationFramework.dll!System.Windows.Controls.Button.OnClick()  Unknown
    PresentationFramework.dll!System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)    Unknown
    PresentationCore.dll!System.Windows.UIElement.OnMouseLeftButtonUpThunk(object sender, System.Windows.Input.MouseButtonEventArgs e)  Unknown
    PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown
    PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target)   Unknown
    PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
    PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)    Unknown
    PresentationCore.dll!System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args, System.Windows.RoutedEvent newEvent)  Unknown
    PresentationCore.dll!System.Windows.UIElement.OnMouseUpThunk(object sender, System.Windows.Input.MouseButtonEventArgs e)    Unknown
    PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown
    PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target)   Unknown
    PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
    PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)    Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args)   Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args)    Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) Unknown
    PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() Unknown
    PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input)  Unknown
    PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport)   Unknown
    PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel)   Unknown
    PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd, MS.Internal.Interop.WindowMessage msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)   Unknown
    PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)    Unknown
    WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown
    WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Unknown
    WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)  Unknown
    WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Unknown
    WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs)   Unknown
    WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)  Unknown
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame)   Unknown
    WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame)   Unknown
    PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore)   Unknown
    PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window)  Unknown
    PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window)  Unknown
    PresentationFramework.dll!System.Windows.Application.Run()  Unknown
    WpfApp1.exe!WpfApp1.App.Main()  Unknown

@TonyHenrique You'd need to post the code for Entidades.Pedido to make sense of this.
WPF is calling Pedido.Equals, maybe to check if DataContext did infact change?

I'd say some C# reflection code has created F# objects containing null values.

@dsyme Yes, DataContext is probably null when this is first assigned for example.

My Entidades.Pedido is defined in F#:

        [<CLIMutable>]
        //[<AddINotifyPropertyChangedInterfaceAttribute>]  // Injects INotifyPropertyChanged code into properties at compile time // https://github.com/Fody/PropertyChanged 
        Pedido = 
        { 
            mutable ID: Guid

            mutable Numero: string

            [<EdgeIn("POSSUI")>]
            mutable Cliente: Pessoa

            [<EdgeOut("POSSUI")>]
            mutable Items: ObservableCollection<ItemPedido>
        }

let PegaFormPedido (id:Guid) : Pedido =
    let t = typeof<Pedido>
    let constructedType = typedefof<Pedido>

    let x = Activator.CreateInstance(constructedType)
    let x_p = x :?> Pedido

    SetProperty constructedType x "ID" (Guid.Parse("6762bad8-086c-4e6a-9abb-6213f0743b0c"))
    SetProperty constructedType x "Numero" ("3a+")

    x_p

Simple thing to rule out: delete all your bin and obj folders, then rebuild. In case it's an incremental build issue. I've had that happen a few times in the past. No amount of Clean, then Build would fix it. I had to physically delete the bin/obj folders.

I deleted both bin and obj but problem persists.
It only happens after I click the button the second time. First time, everything works as expected. On second click, it gives the Exception:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

Call Stack:

    ClassLibrary1.dll!Entidades.Pedido.Equals(Entidades.Pedido obj) F#
>   ClassLibrary1.dll!Entidades.Pedido.Equals(object obj) Line 70   F#
    mscorlib.dll!object.Equals(object objA, object objB)    Unknown
    PresentationFramework.dll!System.Windows.Data.BindingExpression.OnDataContextChanged(System.Windows.DependencyObject contextElement)    Unknown

Ok, does sound like C# creating something null as previously mentioned. I run into this problem sometimes when I let C#-based libs create objects that get passed into F#, such as when deserializing with Newtonsoft.Json.

Maybe this is related to the generic code?

let constructedType = typedefof<Pedido>
let x = Activator.CreateInstance(constructedType)

Given that the C# code is creating a null value, it sounds like the remediation here is to all the appropriate null check in the F# code. I don't think this is an issue in the F# compiler or tools.

From what I know, this null is not being created on my C# code.
Can you give a look?
I created a sample repro, just click the WPF button 3 times and it will throw the Exception:
https://drive.google.com/open?id=1g0TdwvkPsKJWRtHf81kbuuhNtTupQpCB

I could make an even smaller repro:
Create a New F# Console Application (.NET Core), paste this code and run.

open System
module API =
    [<CLIMutable>]
    type Person = { mutable Name : string }

    [<CLIMutable>]
    type Invoice = { mutable Customer: Person }

    let blow () = 
        let constructedType = typedefof<Invoice>    
        let x = Activator.CreateInstance(constructedType)
        x

    [<EntryPoint>]
    let main argv =
        let x = blow ()
        let eq = x.Equals(x);       // This line will throw the Exception
        //let res = x.GetHashCode() // This line will throw the Exception
        0

Or Create a New F# Class Library (.NET Core), and a C# WPF App, reference the F# Class Library.
In the C# side, this will also throw the Exception in the F# code:

private void Button_Click(object sender, RoutedEventArgs e)
{
    var x = API.Actions.blow();
    x.Equals(x);
}

I think that this is related to this issue: https://github.com/Microsoft/visualfsharp/issues/1044

Is it possible to add a warning when nulls are not checked when consuming C#?

@TonyHenrique the problem is by using CreateInstance in conjuction with CLIMuteable you circumvent F# type system, creating an invalid record filled with nulls. You could write functions that would return valid default values for each record type, or just use objects here.

BTW using [<CLIMutable>] records for WPF viewmodels is a minefield.

I noticed here that if I add the option keyword to the fields that references other records types, the Exception does not occur, and it works fine:

[<CLIMutable>]
type Person = { mutable Name : string }

[<CLIMutable>]
type Invoice = { mutable Customer: Person option }

Can it be safely used with this code?

let constructedType = typedefof<Invoice>    
let x = Activator.CreateInstance(constructedType)

I would like to know how to remove the mutable, and make it work in TwoWay DataBinding in WPF/UWP. Then it would be a cleaner and safer code.

@majocha I don't know how your suggested approach would be possible, because I am trying to write something like a simple Graph ORM and need to use Reflection to dinamically fill the fields at runtime.

@TonyHenrique the problem is by using CreateInstance in conjuction with CLIMuteable you circumvent F# type system, creating an invalid record filled with nulls. You could write functions that would return valid default values for each record type, or just use objects here.
BTW using [ < CLIMutable>] records for WPF viewmodels is a minefield.

You are right. I see now that trying to use F# Records + Fody.INotifyPropertyChanged to interop directly with my old WPF code is not good idea.

Now Reading the F# docs, I see this:

If your F# code has to work closely with the .NET Framework or another object-oriented library, and especially if you have to extend from an object-oriented type system such as a UI library, classes are probably appropriate.

If you are not interoperating closely with object-oriented code, or if you are writing code that is self-contained and therefore protected from frequent interaction with object-oriented code, you should consider using records and discriminated unions.

https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/classes#when-to-use-classes-unions-records-and-structures

On this case, I should use F# Classes instead.

Was this page helpful?
0 / 5 - 0 ratings