NuGet C#

Neil HaddleyFebruary 27, 2021

Create, publish and consume a NuGet package using C#.

Recursion

When a function is called, the computer must "remember" the place it was called from... so that it can return to that location with the result once the call is complete. Typically, this information is saved on the call stack... For tail calls, there is no need to remember the caller...

https://en.wikipedia.org/wiki/Tail_call

Some interpreters (and compilers) eliminate the stack frame creation and destruction work when they recognize tail recursion.

C#

Adding a "HaddleyOffice365.dotnet-factorial" package to NuGet.org.

NuGet is the package manager for .NET.

Start by creating a dotnet-factorial repository in the https://github.com/HaddleyOffice365 profile.

New repository will be named dotnet-factorial

New repository will be named dotnet-factorial

Publish to GitHub

Publish to GitHub

Open in Visual Studio Code

Open in Visual Studio Code

Create a .NET solution and the .NET projects

Create a dotnet solution

$ dotnet new sln

Create a class library project and add the new class library project to the solution

$ dotnet new classlib -o dotnet-factorial

$ dotnet sln add ./dotnet-factorial/dotnet-factorial.csproj

Create a test project and add the new test project to the solution

$ dotnet new mstest -o unittests

$ dotnet sln add ./unittests/unittests.csproj

At a reference from the unit tests project to the factorial project.

$ dotnet add ./unittests/unittests.csproj reference ./dotnet-factorial/dotnet-factorial.csproj

Add a .gitignore file to the unit tests project directory and to the factorial project directory.

$ cd dotnet-factorial

$ dotnet new gitignore

$ cd ../unittests

$ dotnet new gitignore

$ cd ..

new solution, new classlib project and new mstest project

new solution, new classlib project and new mstest project

Rename UnitTest1, copy and rename Class1

Rename the generated UnitTest1 class to "UnitTests"

Copy Class1 class and rename to "recursivefunctions.cs"

Rename the generated Class1 class to "iterativefunctions"

Update the file contents:

dotnet test

use "dotnet test" to run the unit test locally on the development machine.

$ dotnet test

dotnet test

dotnet test

Commit to main

Commit updates to the repository.

Commit to main branch

Commit to main branch

Push origin

Push origin

GitHub actions

A GitHub action will ensure that testing is performed automatically.

Add the ".NET By GitHub Actions" workflow

Add the ".NET By GitHub Actions" workflow

GitHub action running

GitHub action running

GitHub action finished

GitHub action finished

GitHub action details

GitHub action details

PackageLicenseExpression, PackageId and Version

Add PackageLicenseExpression, PackageId and Version tags to the Functions.csproj file

dotnet-factorial.csproj

dotnet-factorial.csproj

dotnet pack

use "dotnet pack" to create .nupkg file

$ dotnet pack

dotnet pack

dotnet pack

Listing the NuGet package

Upload the nupkg file to nuget.org.

+ Add new

+ Add new

Browse...

Browse...

Choose for Upload

Choose for Upload

Verify

Verify

Submit

Submit

Successful upload. Status Validating

Successful upload. Status Validating

Status Listed

Status Listed

Consuming the NuGet Package

$ dotnet new console

$ dotnet new gitignore

$ dotnet add package HaddleyOffice365.dotnet-factorial --version 1.0.0

dotnet add package HaddleyOffice365.dotnet-factorial --version 1.0.0

dotnet add package HaddleyOffice365.dotnet-factorial --version 1.0.0

dotnet run

$ dotnet run

dotnet run

dotnet run

UnitTests.cs

TEXT
1using Microsoft.VisualStudio.TestTools.UnitTesting;
2using dotnet_factorial.recursive;
3using dotnet_factorial.iterative;
4
5namespace dotnet_factorial.unittests
6{
7    [TestClass]
8    public class UnitTests
9    {
10        [TestMethod]
11        public void TestMethod()
12        {
13            Assert.AreEqual(362880, recursivefunctions.factorial(9));
14            Assert.AreEqual(362880, recursivefunctions.factorial_tr(9));
15            Assert.AreEqual(362880, iterativefunctions.factorial_it(9));
16
17            Assert.AreEqual(7.257415615307994e+306, recursivefunctions.factorial(170));
18            Assert.AreEqual(7.257415615308004e+306, recursivefunctions.factorial_tr(170));
19            Assert.AreEqual(7.257415615308004e+306, iterativefunctions.factorial_it(170));
20        }
21    }
22}

iterativefunctions.cs

TEXT
1using System;
2
3namespace dotnet_factorial.iterative
4{
5    public class iterativefunctions
6    {
7        public static double factorial_it(int n)
8        {
9            double acc = 1;
10
11            for (int i = n; i > 1; i--)
12            {
13                acc = acc * i;
14            }
15
16            return acc;
17        }
18    }
19}

recursivefunctions.cs

TEXT
1using System;
2
3namespace dotnet_factorial.recursive
4{
5    public class recursivefunctions
6    {
7
8        public static double factorial(int n)
9        {
10            if (n < 2) return 1;
11            return n * factorial(n - 1);
12        }
13
14        private static double fac_tr_aux(int n, double acc)
15        {
16            if (n < 2)
17                return acc;
18            return fac_tr_aux(n - 1, n * acc);
19        }
20
21        public static double factorial_tr(int n)
22        {
23            return fac_tr_aux(n, 1);
24        }
25
26    }
27}

dotnet.yml

YAML
1name: .NET
2
3on:
4  push:
5    branches: [ main ]
6  pull_request:
7    branches: [ main ]
8
9jobs:
10  build:
11
12    runs-on: ubuntu-latest
13
14    steps:
15    - uses: actions/checkout@v2
16    - name: Setup .NET
17      uses: actions/setup-dotnet@v1
18      with:
19        dotnet-version: 5.0.x
20    - name: Restore dependencies
21      run: dotnet restore
22    - name: Build
23      run: dotnet build --no-restore
24    - name: Test
25      run: dotnet test --no-build --verbosity normal

dotnet-factorial.csproj updates

XML
1<PackageLicenseExpression>MIT</PackageLicenseExpression>
2    <PackageId>HaddleyOffice365.dotnet-factorial</PackageId>
3    <Version>1.0.0</Version>
4    
5    <Title>DotNet Factorial Functions</Title>
6    <Authors>Neil Haddley</Authors>
7    <PackageProjectUrl>
8    https://github.com/haddleyoffice365/dotnet-factorial
9    </PackageProjectUrl>
10    <Description>Recursive and Iterative functions in C#.</Description>

Program.cs

TEXT
1using System;
2using dotnet_factorial.iterative;
3using dotnet_factorial.recursive;
4
5namespace dotnet_factorial_console
6{
7    class Program
8    {
9        static void Main(string[] args)
10        {
11            Console.WriteLine("factorial of 9 is {0}",iterativefunctions.factorial_it(9));
12            Console.WriteLine("factorial of 9 is {0}",recursivefunctions.factorial(9));
13            Console.WriteLine("factorial of 9 is {0}",recursivefunctions.factorial_tr(9));
14        }
15    }
16}