{ "cells": [ { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "[this doc on github](https://github.com/dotnet/interactive/tree/main/samples/notebooks/csharp/Docs)\n", "\n", "# Variable Sharing\n", "\n", ".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](https://github.com/dotnet/interactive/blob/master/docs/kernels-overview.md) for three different languages within the same process. You can share variables between .NET subkernels using the `#!share` magic command." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!csharp\n", "var x = \"C# subkernel value\";\n", "x" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "fsharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!fsharp\n", "#!share --from csharp x\n", "sprintf \"%s, accessed from F# subkernel\" x" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "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:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "fsharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!fsharp\n", "open System.Collections.Generic\n", "\n", "let list = List()\n", "list.Add \"Added by F#\"\n", "list " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!csharp\n", "#!share --from fsharp list\n", "\n", "list.Add(\"Added by C#\");\n", "\n", "list" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "fsharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!fsharp\n", "\n", "list" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "# Direct data entry with `#!value`\n", "\n", "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`.\n", "\n", "There are three ways to use `#!value` to get data into your notebook session:\n", "\n", "### 1. From the clipboard\n", "\n", " 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.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!value --name someJson\n", " \n", "{ \n", " \"what\": \"some JSON\", \n", " \"why\": \"to share it with another subkernel\"\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!share someJson --from value\n", " \n", "using Newtonsoft.Json.Linq;\n", "var jObject = JObject.Parse(someJson);\n", "jObject.ToString()" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "\n", "### 2. From a file\n", "\n", "If the data you want to read into your notebook is stored in a file, you can use `#!value` with the `--from-file` option:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!value --from-file data.json --name someJson" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!share someJson --from value\n", "someJson" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "\n", "### 3. From a URL\n", "\n", "You can pull data into your notebook from a URL as well, using the `--from-url` option. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!value --from-url https://dot.net --name dn" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!share --from value dn\n", "display(dn, \"text/html\");" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "## Specifying a MIME type\n", "\n", "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:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!value --name someJson --mime-type application/json\n", " \n", "{ \n", " \"what\": \"some JSON\", \n", " \"why\": \n", " [\n", " \"to share it with another subkernel\",\n", " \"to see it in a treeview\"\n", " ]\n", "}" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "This also causes the value to be saved in your `.ipynb` file, something that would not otherwise happen.\n" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "\n", "This also effectively stores the value in your `.ipynb` file, something that would not otherwise happen.\n" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "## Limitations\n", "\n", "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.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!csharp \n", "public class DefinedInCSharp { }\n", "\n", "var csharpInstance = new DefinedInCSharp();" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "fsharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [ "#!fsharp\n", "#!share --from csharp csharpInstance\n", "csharpInstance" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": ".NET (C#)", "language": "C#", "name": ".net-csharp" }, "language_info": { "file_extension": ".cs", "mimetype": "text/x-csharp", "name": "C#", "pygments_lexer": "csharp", "version": "8.0" }, "polyglot_notebook": { "kernelInfo": { "defaultKernelName": "csharp", "items": [ { "aliases": [], "name": ".NET" }, { "aliases": [ "C#", "c#" ], "languageName": "C#", "name": "csharp" }, { "aliases": [ "F#", "f#" ], "languageName": "F#", "name": "fsharp" }, { "aliases": [], "languageName": "HTML", "name": "html" }, { "aliases": [ "js" ], "languageName": "JavaScript", "name": "javascript" }, { "aliases": [], "languageName": "KQL", "name": "kql" }, { "aliases": [], "languageName": "Mermaid", "name": "mermaid" }, { "aliases": [ "powershell" ], "languageName": "PowerShell", "name": "pwsh" }, { "aliases": [], "languageName": "SQL", "name": "sql" }, { "aliases": [], "name": "value" } ] } } }, "nbformat": 4, "nbformat_minor": 2 }