Home > dotnet > Interactive C# with Polyglot Notebooks

Interactive C# with Polyglot Notebooks

Bringing the data science notebook experience to dotnet development

by
Published: Last Updated on

Cover image created by Matt Eland using MidJourney

Have you ever wanted to do a simple demonstration of a class, method, or line of C# code without needing a full instance of Visual Studio or a console application? Polyglot Notebooks can help with that by bringing an interactive C# development experience in the form of an interactive notebook.

In this article, I'm going to show you how to get started with Polyglot Notebooks in VS Code. We'll see how C# code can be used in a notebook to perform lightweight demonstrations and experiments without needing the weight of a more formal program. I'll also highlight a few scenarios where this workflow is potentially more helpful than others, such as when working with ML.NET IDataView objects.

This content is also available on YouTube.

The Value of Notebooks

Before we dive into Polyglot Notebooks specifically, let's talk about notebooks in general and why you would even want them.

A few years ago I didn't get it. I didn't understand why anyone would ever need to have an interactive code notebook that wasn't a deployable program in its own rite. And then I tried Jupyter Notebooks at after seeing a friend and mentor having a blast with it and everything changed:

Jupyter Notebooks showed me how they let me mix together Python and Markdown cells into a notebook document to perform iterative data analysis and data science experiments. I saw that I could do lightweight exploratory work without needing to create a full program and repeatedly run it and test it.

Notebooks are just code that can be committed to source control. This means you can share a created notebook with developers, analysts, managers, and even executives and have them gain insights through well-documented code that they can easily tweak and run on their own without machine-specific configuration.

For me, this was the moment that Python made sense to me as something I would want to use. Of course, since then I've found many more compelling reasons to do Python development, including data science libraries like SciKit-learn, FairLearn, TensorFlow, Keras, and others. But Notebooks was what convinced me of the promise of the Python language in a modern organization.

Introducing Polyglot Notebooks (formerly .NET Interactive)

After playing enough with Jupyter Notebooks, I couldn't help but feel that the dotnet community was "missing out" until the .NET Interactive Notebooks extension brought the notebook experience to dotnet developers.

.NET Interactive Notebooks, now rebranded to Polyglot Notebooks, allows you to use a wide variety of dotnet languages within Jupyter Notebooks by providing a custom kernel to execute Jupyter Notebook code.

The Polyglot Notebooks kernel allows us to run code cells written in:

  • C#
  • F#
  • JavaScript
  • SQL
  • HTML
  • PowerShell
  • Kusto Query Language (KQL)
  • Mermaid (diagram-based markdown)

Note: Notably, the list does not seem to currently include VB.

In fact, with many of these languages you can actually mix and match languages in the same notebook and even share variables between cells of different languages (with some added commands).

While there's a wealth of interesting and unusual things in this list to discuss, we're going to focus on the basic experience for C# developers with the remainder of this article. Please let me know if you have interest in more detailed explorations of cross-language notebooks and I'll add that to my content development queue.

Setting up Polyglot Notebooks for C# Development

If you've never worked with Jupyter or Polyglot Notebooks before, I have a few steps here to help you get started. However, technology changes rapidly and you should consult the official documentation page for the extension for more up-to-date instructions.

In order to work with Polyglot Notebooks, you'll need to have a few things installed and running:

  • Python
  • Jupyter Notebooks
  • Visual Studio Code
  • .NET 7 SDK
  • The Jupyter Notebooks Extension
  • The Polyglot Notebooks Extension

Installing Python & Jupyter

If you do not yet have Python or Jupyter Notebooks installed on your machine, I recommend you install Anaconda Individual Edition (or a different edition should individual edition not meet your licensing needs).

Anaconda is a stand-alone data science environment containing Python, Jupyter Notebooks, and a variety of data science packages in a pre-configured bundle. This makes it an easy choice for getting started with Python development on a hobbyist developer's machine.

Installing Polyglot Notebooks in VS Code

Once you have some flavor of Jupyter Notebooks installed, you'll need to install and open Visual Studio Code.

You'll also want to make sure that the .NET 7 SDK is installed on your system.

After that you'll need to go to the extensions tab on the sidebar and install the following extensions:

Once these extensions are installed, you should be able to press Control + Shift + P to open the command palette in VS Code. From there, select Polyglot Notebook: Create a new blank notebook

When prompted, you can choose to create it as a .dib or .ipynb. I typically save mine as .ipynb files since I know the extension from development with Jupyter Notebooks.

Next select the language you want to work with. In this case I chose C#.

Once you do this you should see a blank notebook with a single C# cell as pictured below:

Using Polyglot Notebooks for Interactive C# Development

Once you have Jupyter Notebooks installed along with VS Code with the Polyglot Notebooks extension, you should be able to add and execute cells in your notebook.

Using C# in a Notebook

In your C# cell, you can add in some simple C# code such as:

Console.WriteLine("Hello Polyglot Notebooks!");

This code can take up multiple lines if you need it to, or it could be a value on a single line.

Once your code is present, press the "play" button to the left of the cell or press Control + Enter to execute the cell.

You should see the notebook briefly compile then execute the cell:

Here we see your code executing and its output rendered below the cell.

Congratulations, you just ran your first bit of C# code from a notebook!

Code Cells with Variables

A simple console statement isn't terribly interesting, so let's take a look at how code cells can interact with each other.

You can use code cells to declare variables that can be used in other code cells.

Hover your mouse below the cell you just ran and click on the + Code button to add a new code cell below the one you just ran.

You should now see a new cell. Type in the following C# code and execute the cell:

decimal itemPrice = 9.99M;
int quantityPurchased = 10;

decimal totalPrice = quantityPurchased * itemPrice;

// If you end a cell with a variable, that value is displayed below the cell
totalPrice

Note that code cells can consist of multiple statements and include comments. Also note that if you end a cell with a variable on its own line, its value will automatically be logged below the cell when the code runs.

This is why we see the value 99.90 displayed below the cell when the code above is executed:

Using Classes & Sharing Variables Between Cells

Simple cells on their own would be a little boring, so let's mix it up a bit by adding in classes, objects, and sharing variables between cells.

Add another cell and include the following code:

// Declare a class
public class Purchase 
{
    public string ItemName {get; init;}
    public decimal TotalPrice {get; init;}
}

// Instantiate that class
Purchase cablesPurchase = new() {
    ItemName = "USB Cables",
    TotalPrice = totalPrice // Variable from cell above
};

// Log the purchase to the notebook
cablesPurchase

When we run this, we see a tabular display of the properties of that Purchase instance:

This, to me, is one of my favorite aspects of Polyglot Notebooks for C# Development: we didn't need to override ToString to get value out of logging the object at the end of the cell.

You may encounter errors from time to time stating that variables from the cells above are no longer defined. If this occurs, you may need to re-run the earlier cells to resolve the issue.

You can run cells in a notebook in any order and re-run cells as many times as you would like. There's also the Run All button at the top of the notebook to conveniently run the entire notebook.

As a final note before we move on, if you're ever curious what values your notebook is keeping track of from cell to cell, you can click Values on the toolbar at the top of your notebook to bring up the Polyglot Notebook: Values section in the footer:

Documentation with Markdown

I can't talk about Notebooks without mentioning the ability to add in markdown cells.

Add another cell below your last code cell, but this time choose + Markdown

Markdown cells support a GitHub-flavored Markdown syntax and allow you to add in headers, documentation paragraphs, links, and even lists and images into your code.

To demonstrate this, add in the following markdown code:

## Additional Topics

The sections below include information on some more advanced topics including:

- Using statements to use classes from other namespaces
- Installing NuGet Packages
- Working with `IDataViews` in [ML.NET](https://dotnet.microsoft.com/en-us/apps/machinelearning-ai/ml-dotnet)

When you run this code you should see the markdown cell get replaced with formatted text:

If you want to edit the Markdown again, you can always double-click the cell to edit it.

Using Statements and Collections in Notebooks

Let's take a look at something a bit more complex by adding a number of strings to a list.

Since List<T> is declared inside of the Systems.Collections.Generic namespace, we'll need to add a using statement to import that.

Let's add a new code cell and add some strings to a list:

using System.Collections.Generic;

List<string> states = new() {"Ohio", "Idaho", "Confusion"};

states

This code gains access to the System.Collections.Generic namespace and then adds in a new list of strings containing "Ohio", "Idaho", and "Confusion". Finally, this code displays the current value of that list to the notebook as shown below:

Again, we're taking advantage of the convenient pretty-printing of objects that Polyglot Notebooks gives us by default.

Here's another cool thing about this: we actually didn't need the using System.Collections.Generic statement above. The collections generic namespace is automatically available in Polyglot Notebooks because it is used so frequently. It is not immediately clear to me where, if anywhere, this is documented in Polyglot Notebooks or what namespaces are available and which ones are not, but this particular namespace does not explicitly need to be imported.

Installing NuGet Packages

Every so often you'll want to work with custom code libraries that are not part of the base class library. When this happens, you'll need to use a "magic command" to install them via NuGet Package Manager.

For example, the code below will install the Microsoft.ML namespace used by ML.NET, then adapt our states data into an IDataView commonly used by ML.NET:

// Install the Microsoft.ML package used by ML.NET
#r "nuget:Microsoft.ML"

// Gain access to the namespace
using Microsoft.ML;

// Create the MLContext ML.NET revolves around
MLContext context = new();

// Create an IDataView from our states data
IDataView stateDataView = context.Data.LoadFromEnumerable<string>(states);

// Display data from the stateDataView
stateDataView // or stateDataView.Preview() for more info

This will produce the following output:

Note that this does tell me that it installed the Microsoft.ML library at its latest non-preview version, which was 2.0.0 at the time of writing this article. See the Polyglot Notebook documentation for steps on installing only a specific version of a dependency.

Next Steps

This is only an introductory article on Polyglot Notebooks, but I hope it showed you their power.

The ability to quickly write and run C# code in a sharable notebook format can be very powerful and is particularly useful for things like:

  • Documenting an open source library in an interactive notebook format
  • Teaching people aspects of dotnet languages (including C#)
  • Prototyping the public API of a class you're designing
  • Aggregating data using LINQ
  • Manipulating tabular data using ML.NET IDataViews
  • Conducting data science experiments using ML.NET

I'm personally very excited to use Polyglot Notebooks to explore data and run machine learning experiments in the year to come. I'd love to hear what you find most interesting about this projects and ways you've used it or are currently considering using it.

This post is part of C# Advent 2022. Check out the C# Advent site for a full list of other posts on relevant C# topics.

Author

  • Matt Eland
    Microsoft MVP in AI, Author of "Refactoring with C#"

    Matt Eland is a software engineering leader and data scientist who has served as a senior engineer, software engineering manager, professional programming instructor, and has helped build enterprise-level software at a variety of organizations before distinguishing himself as a Microsoft MVP in Artificial Intelligence by using technology to accomplish ridiculous things in the name of science and teaching others. Matt makes it his job to learn new things and share them with others through articles, videos, and talks at user groups and conferences covering a wide range of topics from software architecture to programming topics to artificial intelligence and data science. Matt is a current data analytics master's student, an AI Specialist at Leading EDJE, is the author of "Refactoring with C#" and is creating a LinkedIn course and book on Computer Vision on Azure. Matt occasionally sleeps as well.

    View all posts

10 comments

Dew Drop – December 15, 2022 (#3838) – Morning Dew by Alvin Ashcraft December 15, 2022 - 8:18 am

[…] Interactive C# with Polyglot Notebooks (Matt Eland) […]

Reply
rsaag January 7, 2023 - 1:07 pm

Thanks for the great introduction to Polyglot Notebooks. Can you cover topics on using SQL language in Polyglot Notebooks and sharing variables between different SQL language cells? And also sharing variables across different cell languages like C# and SQL?

Reply
Matt Eland January 7, 2023 - 1:31 pm

I love this. I’m definitely adding this to my content backlog. Thank you for sharing your interest!

Reply
David Cuccia March 12, 2023 - 6:15 pm

Great post! Glad the word is getting out on this awesome tool.

Reply
Text-Based Entity Relationship Diagrams with Mermaid.js April 8, 2023 - 4:54 pm

[…] Polyglot Notebooks […]

Reply
Creating Class Diagrams with Mermaid.js April 8, 2023 - 11:45 pm

[…] can use Mermaid.js in a variety of places, including GitHub markdown, Polyglot Notebooks, and a live mermaid […]

Reply
Sequence Diagrams in Markdown with Mermaid.js April 11, 2023 - 12:00 am

[…] Mermaid.js is available in a variety of tools, but I most frequently use it in GitHub markdown files and in Polyglot Notebooks. […]

Reply
Mapping User Journeys with Mermaid.js April 13, 2023 - 12:16 am

[…] is supported in a variety of tools and services including GitHub markdown, Polyglot Notebooks, a Visual Studio extension, and a live online editor. Mermaid.js can also be manually included in […]

Reply
Creating Gantt Charts with Markdown and Mermaid.js April 14, 2023 - 12:28 am

[…] that supports Mermaid.js. This is a surprisingly large number of places including GitHub markdown, Polyglot Notebooks, and the online Mermaid.js […]

Reply
How to Make Flowcharts with Mermaid.js April 15, 2023 - 10:45 pm

[…] are a growing number of places that support Mermaid.js diagrams including GitHub markdown, Polyglot Notebooks, and the Mermaid.js live editor. You can also import Mermaid.js to transform markdown on your […]

Reply

Leave a Reply

Related Content

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More

Discover more from The New Dev's Guide

Subscribe now to keep reading and get access to the full archive.

Continue reading