NuGet C#
Neil Haddley • February 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

Publish to GitHub

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
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
Commit to main
Commit updates to the repository.

Commit to main branch

Push origin
GitHub actions
A GitHub action will ensure that testing is performed automatically.

Add the ".NET By GitHub Actions" workflow

GitHub action running

GitHub action finished

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

dotnet-factorial.csproj
dotnet pack
use "dotnet pack" to create .nupkg file
$ dotnet pack

dotnet pack
Listing the NuGet package
Upload the nupkg file to nuget.org.

+ Add new

Browse...

Choose for Upload

Verify

Submit

Successful upload. Status Validating

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 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}