.NET Interactive enables you to write code in multiple languages within a single notebook and in order to take advantage of those languages' different strengths, you might find it useful to share data between them. By default, .NET Interactive provides subkernels for three different languages within the same process. You can share variables between .NET subkernels using the #!share
magic command.
#!csharp
var x = "C# subkernel value";
x
#!fsharp
#!share --from csharp x
sprintf "%s, accessed from F# subkernel" x
Variables are shared by reference for reference types. A consequence of this is that if you share a mutable object, changes to its state will be visible across subkernels:
#!fsharp
open System.Collections.Generic
let list = List<string>()
list.Add "Added by F#"
list
#!csharp
#!share --from fsharp list
list.Add("Added by C#");
list
#!fsharp
list
#!value
¶It's common to have text that you'd like to use in a notebook. It might be JSON, CSV, XML, or some other format. It might be in a file, in your clipboard, or on the web. The #!value
magic command is available to make it as easy as possible to get that text into a variable in your notebook. An important thing to know is that #!value
is an alias to a subkernel designed just to hold values. This means that once you store something in it, you can access it from another subkernel using #!share
.
There are three ways to use #!value
to get data into your notebook session:
The simplest way to use #!value
is to paste some text into the cell. The text will be stored as a string, but unlike using a string
literal in C#, F#, or PowerShell, there's no need to escape anything.
#!value --name someJson
{
"what": "some JSON",
"why": "to share it with another subkernel"
}
#!share someJson --from value
using Newtonsoft.Json.Linq;
var jObject = JObject.Parse(someJson);
jObject.ToString()
If the data you want to read into your notebook is stored in a file, you can use #!value
with the --from-file
option:
#!value --from-file data.json --name someJson
#!share someJson --from value
someJson
You can pull data into your notebook from a URL as well, using the --from-url
option.
#!value --from-url https://dot.net --name dn
#!share --from value dn
display(dn, "text/html");
Regardless of which of these approaches you use, you can additionally choose to display the value in the notebook at the time of submission by using the --mime-type
option. This accomplishes a few things. If your notebook frontend knows how to display that mime type, you can see it appropriately formatted:
#!value --name someJson --mime-type application/json
{
"what": "some JSON",
"why":
[
"to share it with another subkernel",
"to see it in a treeview"
]
}
This also causes the value to be saved in your .ipynb
file, something that would not otherwise happen.
This also effectively stores the value in your .ipynb
file, something that would not otherwise happen.
Variable sharing has some limitations to be aware of. When sharing a variable with a subkernel where its compilation requirements aren't met, for example due to a missing using
(C#) or open
(F#) declaration, a custom type defined in the notebook, or a missing assembly reference, #!share
will fail. This limitation may be lifted in the future but for now, if you want to share variables of types that aren't imported by default, you will have to explicitly run the necessary import code in the destination kernel.
#!csharp
public class DefinedInCSharp { }
var csharpInstance = new DefinedInCSharp();
#!fsharp
#!share --from csharp csharpInstance
csharpInstance