# NumSharp: a NumPy-shaped NDArray library for .NET

> NumSharp gives C# and F# a NumPy-style NDArray with broadcasting, slicing views and runtime-generated kernels. It is aimed at .NET teams that want array code without embedding CPython, and its compatibility target is NumPy 2.x.

**SciSharp/NumSharp** — High Performance Computation for N-D Tensors in .NET, similar API to NumPy.

- Repository: https://github.com/SciSharp/NumSharp
- Website: https://scisharp.github.io/NumSharp/
- Stars: 1,481 · Forks: 205
- Language: C#
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/scisharp-numsharp

## The gap NumSharp fills for C# numerical code

A .NET service that needs array math usually faces two options. It can call into CPython through an interop layer, which adds a runtime, a deployment dependency and a marshalling boundary. Or it can write loops over multidimensional arrays by hand, which is where stride bugs and accidental copies accumulate. NumSharp takes a third route: it implements the array type in managed .NET and shapes the API after NumPy. The README describes it as "a native .NET array library with a NumPy-shaped API" and lists NDArray, broadcasting, slicing views, dtype-aware np.* functions and unmanaged storage as the pieces. The audience is therefore specific. It is for scientific computing and numerical utilities written in C# or F#, and for machine learning infrastructure where the surrounding code is already .NET. The README states the compatibility target plainly: NumPy 2.x, and when the two disagree, "NumPy is treated as the source of truth." That sentence is the project's contract, and it is also the standard you should hold it to.

## How NDArray, views and generated kernels fit together

The core type is NDArray, an N-dimensional array carrying shape, strides, offset and view metadata. Because a slice is described by stride and offset rather than by copying, an expression like a[":, 1::2"] produces a window over the same storage. Broadcasting follows the NumPy rule of expanding shapes without materializing repeated values, so a small operand can participate in a larger operation without a full-size temporary. On top of that layout model sit two execution mechanisms. The first is runtime IL generation: kernels are generated for supported dtype and layout combinations and translated to assembly through the JIT, with SIMD paths where the layout allows. The second is an NDIter-style iterator and fusion layer, which the README ties to fused np.evaluate expressions for reducing intermediate allocations. The practical consequence is that performance depends on the combination you hit. A contiguous float array on a supported kernel takes a fast path; an unusual dtype or a strided view may fall back. The README points to a benchmark dashboard that compares NumSharp with NumPy 2.4.2 across an operation matrix, three size tiers and the NDIter, layout, operand, cast and fusion subsystems, and it describes those numbers as tracked release snapshots rather than ad hoc figures. Read the per-subsystem breakdown before assuming a headline result applies to your shapes.

## Install NumSharp and run a first slice-and-reduce example

The package is distributed on NuGet, and the README gives a single command to add it to a project. Run this from the directory of the project that will use it.

```bash
dotnet add package NumSharp
```

The README's first example creates a 3 by 4 array, takes a strided window over columns 1 and 3, prints the window, then reduces it along axis 0. The string index "[:, 1::2]" is the NumPy slicing syntax expressed as text, which is why the surrounding code stays close to Python.

```csharp
using NumSharp;

var a = np.arange(12).reshape(3, 4);
var window = a[":, 1::2"];

Console.WriteLine(window);
Console.WriteLine(np.sum(window, axis: 0));
```

Expect the window to be a 3 by 2 array holding the values from columns 1 and 3, and the sum to be a length-2 result adding down the rows. The README shows the equivalent Python so you can compare shapes directly. If you want to build and test the repository itself rather than consume the package, the README gives these two commands.

```bash
dotnet build test/NumSharp.Tests/NumSharp.Tests.csproj --configuration Release
```

```bash
dotnet test test/NumSharp.Tests/NumSharp.Tests.csproj \
  --configuration Release \
  --no-build \
  --framework ne
```

Note the --framework value as printed in the README; it is not the usual target framework moniker, so copy it rather than retyping it from memory. The repository also ships runnable examples under examples/, including NeuralNetwork.NumSharp and NumSharp.Interop.pythonnet.Examples, which are useful when you want to see the API used in a larger program than a console snippet.

## Coverage is the real constraint, not the API shape

NumSharp is a port in progress, and the README does not hide it. It links a coverage and support dashboard that it calls "the full implementation roadmap to complete 100% NumPy porting," with an explorer for checking individual functions. That wording is the honest limitation: a NumPy-shaped API is not the same as a complete NumPy. If your code depends on a corner of the library that has not been ported, the shape of the call will look right and the behavior will not be there. The second limitation is performance predictability. Kernels are generated for supported dtype and layout combinations, so the fast path is conditional. Code that passes contiguous arrays of a common dtype sees one profile; code that chains many small strided operations may see another, and the fusion layer exists precisely because intermediate allocations are a cost worth removing. The third case is the wrong tool entirely. If your numerical stack already lives in Python, or if you need the surrounding Python ecosystem rather than the array type, an interop package that calls into CPython is the smaller change. NumSharp's value is avoiding that boundary, so adding it back as a bridge defeats the purpose. The repository does include a pythonnet interop example, but that is for mixed scenarios, not for replacing a Python-first pipeline.

## NumSharp against calling NumPy from .NET

The realistic alternative is not another C# array library. It is keeping NumPy and reaching it from .NET through an interop layer such as pythonnet, which the repository itself demonstrates in examples/NumSharp.Interop.pythonnet.Examples. The difference is architectural rather than cosmetic. With interop, the array lives in CPython, the full NumPy 2.x surface is available because it is NumPy, and every call crosses a managed-to-native boundary with conversion of arguments and results. With NumSharp, the array lives in the .NET heap, calls stay in-process, and the surface is whatever the port has implemented. That trade is easy to state and hard to reverse later. Interop buys completeness and costs a Python runtime in your deployment plus per-call marshalling. NumSharp buys in-process execution and a managed deployment and costs you the parts of NumPy that are still on the roadmap. If your application is a .NET service that happens to do numerical work, the second trade is usually the better one. If your application is a Python analysis pipeline with a .NET front end, the first is.

## Maintenance, licensing and what an upgrade costs

The repository is not archived, and the last push was on 2026-09-07. Releases are versioned and labelled: v0.70.0 as a stable release on 2026-09-06, v0.60.0 as a stable release on 2026-06-28, and v0.50.0-prerelease on 2026-04-12, described as the long indexing release. The pattern suggests the project is still moving toward its porting goal, and the prerelease label on 0.50.0 is a reminder that some versions are not stable. Treat the version you pin as a decision, not a default. The upgrade cost is dominated by behavior alignment rather than API churn, because the project's stated rule is that NumPy wins when the two disagree. A release that tightens NumPy compliance can therefore change results in code that was written against the previous behavior, especially around dtype promotion, casting and indexing. The benchmark dashboard publishes per-release snapshots, so a performance regression between versions is visible if you compare snapshots rather than reading one. Licensing is Apache-2.0, which is permissive and includes an explicit patent grant; that is a summary of the identifier, not legal advice, and you should read LICENSE in the repository if your organization has specific requirements. The practical upgrade check is the test filter given in the README, run against the version you are moving to.

## Conclusion

Adopt NumSharp when your numerical code already lives in .NET and you want NDArray semantics rather than a CPython bridge. Do not adopt it if you need the full NumPy surface today or a mature third-party ecosystem on top of the array type. Before committing, open the coverage and support dashboard and check that the functions you depend on are implemented, then run the CI-style test filter against the version you are considering.

## FAQ

### What exactly does NumPy do, and how does NumSharp relate to it?

NumSharp is a native .NET array library with a NumPy-shaped API, built around an NDArray type with shape, strides, offsets and view semantics. Its compatibility target is NumPy 2.x, and when the two differ, the README states that NumPy is treated as the source of truth.

### Is Cython faster than NumPy, and does NumSharp take a similar approach?

The README does not compare NumSharp with Cython. What it does describe is runtime IL generation and SIMD fast paths for supported dtype and layout combinations, with benchmarks published as tracked release snapshots comparing NumSharp with NumPy 2.4.2.

### Is SciPy still used, and does NumSharp cover the same ground?

SciPy is outside NumSharp's scope. NumSharp covers the array layer: NDArray, broadcasting, dtype-aware np.* functions, reductions, comparisons, random sampling, I/O and formatting, with a coverage dashboard tracking the remaining NumPy porting work.

### Can I learn NumPy in 10 minutes, and is NumSharp's API close enough to reuse that knowledge?

NumSharp deliberately mirrors the NumPy programming model, and the README shows the same slice-and-reduce example in both languages: np.arange(12).reshape(3, 4) followed by a[":, 1::2"] and np.sum(window, axis: 0). Familiarity with NumPy transfers to the API shape, though the README describes the port as still in progress.

## Sources

- [License: Apache-2.0](https://github.com/SciSharp/NumSharp/blob/master/LICENSE)
- [Project website](https://scisharp.github.io/NumSharp/)
- [README](https://github.com/SciSharp/NumSharp/blob/master/README.md)
- [Releases](https://github.com/SciSharp/NumSharp/releases)
- [SciSharp/NumSharp on GitHub](https://github.com/SciSharp/NumSharp)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/scisharp-numsharp
