4

I have used binary serialization to save an F# record from a C# class. All works fine:

F#:

type GameState =
    {
        LevelStatus : LevelStatus
        Grid : Variable<Option<Ball> [,]>
        ...
    }
let game_state : GameState = aGameState()

C#:

public void OnSaveGame() {
    using (var stream = File.Open("game_status.sav", FileMode.Create))
    {
        var binary_formatter = new BinaryFormatter();
        binary_formatter.Serialize(stream, PuzzleBobble.game_state);
    }
}

Now, I'm refactoring my F# module and I would like to have a mutable record to serialize:

let mutable game_state = aGameState()
game_state <- myGameState()

This way the file is created but when I try to deserialize it I get a null object.
I've changed nothing of my previous implementation, except the added mutable keyword.

My question is: is there anything wrong with serialization of a mutable F# record? Or serialization it self is right, and I have to look for a different error somewhere else in my code?

EDIT:

Even accessing the record through methods like suggested @Brian, it seems not to work.

Here's some more details. When I deserialize the previous saved object this way (that works without game_state declared mutable):

public void OnLoadGame() {
        using (var stream = File.Open("game_status.sav", FileMode.Open))
        {
            var binary_formatter = new BinaryFormatter();
            try
            {
                GameLogic.GameState state = binary_formatter.Deserialize(stream) as GameLogic.GameState;
                GameLogic.load_game_state(state);
            }
            catch (ArgumentNullException e) {
                Console.WriteLine(e.Message);  
            }       


        }
    }

I get the following exception:

'System.ArgumentNullException' in FSharp.Core.dll

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
  • I think you meant to write `let mutable game_state = aGameState() ` instead of `let mutable game_state <- aGameState() ` – John Palmer Dec 19 '11 at 22:10
  • @John Palmer: well, ok. But that isn't the problem. – Heisenbug Dec 19 '11 at 22:16
  • Is the record itself mutable, or is it an immutable record stored in a mutable variable? Your example only shows the latter... – Joel Mueller Dec 19 '11 at 23:26
  • @Joel Mueller: it's an immutable record stored into a mutable variable. Some fields of the record are mutable too. – Heisenbug Dec 19 '11 at 23:42
  • What does the debugger tell you about "state" after you Deserialize? I'm unclear why you'd see the exception being raised in FSharp.Core.dll if Deserialize or the cast was the one throwing. – fmr Dec 21 '11 at 00:45
  • @fmr: there's nothing inside 'state' because Deserialized doesn't return and raised a ArgumentNullException. When I catch it and print the message, it's : first-chance exception of type 'System.ArgumentNullException' in FSharp.Core.dll – Heisenbug Dec 21 '11 at 00:55
  • Ok - so the question remains: why is the exception says it's raised from FSharp.Core.dll if the thrower is BinaryFormatter. The next guess would be some out-of-order execution of toplevel initializations in the F# modules (assuming that you're doing the deserialization on a freshly running instance of your app). Debugger w/ interception of ArgumentNullException would be useful. – fmr Dec 21 '11 at 01:10
  • @fmr: I did the following: 1)I tried to define game_state immutable and all works 2) I tried to add a field to GameState of type mutable with game_state immutable and doesn't work anymore. It seems that a mutable field cannot be serialized – Heisenbug Dec 21 '11 at 03:26
  • Can you give a complete repro? – J D Dec 27 '11 at 12:17
  • @Jon Harrop: Actually I can't . I wasn't still using version control, so I can't rollback to that point. Anyway I solved not using a mutable game_state. If you are interested at the problem, the whole project now is on codeplex: http://bugamove.codeplex.com/. Thanks for the attention. – Heisenbug Dec 27 '11 at 13:28

1 Answers1

1

I have once seen some weird bug where module-scoped mutable variables in F# libraries were not properly initialized, is it possible you're hitting that?

If you change the code to define

let getGameState() = game_state
let setGameState(x) = game_state <- x

and then use the get/set functions, instead of referring to the mutable variable directly, does the problem go away? If so, this might be an exotic compiler bug that we know about.

Brian
  • 117,631
  • 17
  • 236
  • 300