So, I spent some more time with this and analyzed the results of various syntactic variants in IL to see what F# is doing. As a result, I can see that as long as my fields are "just" mutables and not ref cells, they'll always get wrapped in a ref cell instance before being passed by reference.
Since using a ref cell is the only way I'm aware of to force the F# compiler to pass the variable by reference (IOW - generate the "Type&" IL instead of simply "Type"), the solution that uses ref cells for all my fields seems the best one because I avoid creating and dropping them all the time.
The difference in IL is this - passing by value:
call instance void [ClassLibrary1]ClassLibrary1.Class1::TakeString(string)
Passing by reference:
call instance void [ClassLibrary1]ClassLibrary1.Class1::DoSomething(string&)
It seems kind of weird that the ref cells should be the only way to do this. If I have a mutable variable, why is there no way to say "pass it to this function by reference", IOW tell the compiler to generate "Type&" IL? I'm sure there's something I'm not seeing, but creating a load of ref cells in this use case seems like a great waste of time and resources.
Thanks
Oliver