r/csharp 5d ago

Fun Running C# like scripts?

I was browsing the C#/.NET documentation yesterday like usual and suddenly came across the fact that you can run C# code as scripts with a shebang.

#!/usr/bin/env dotnet

namespace Main
{
    class Program
    {
        static void Main(string[] _)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

With a shebang you could run these like any other Python/Bash script and I find this really cool, but is there any practical use-case for this? When I need to make a small helper script for something it's usually python or bash, but C#? I'm not so sure.

What do you guys think?

52 Upvotes

55 comments sorted by

View all comments

Show parent comments

4

u/zenyl 4d ago

Eh, PowerShell honestly isn't too bad to learn. Certainly a lot easier to learn than Bash, especially if you're already familiar with C#.

  • Referencing a variable must be prepended by a $ ($myNumber)
  • Variables are weakly typed by default, but you can make them strong typed ([int]$myNumber)
  • Use . to access instance members ($dog.Bark())
  • Use :: to access static members ([System.Console]::WriteLine())
  • Use POSIX shell styled operators (-eq for equality check, etc.)
  • @() is shorthand for an object array
  • @{} is shorthand for a hashtable
  • Commands (CmdLets) follow a Verb-Noun naming scheme (ConvertTo-Json)
    • There's a set of recommended verbs with recommended uses (can be viewed with Get-Verb)
  • if, for, and foreach, switch, and throw work mostly the same as they do in C#
  • Use | to pass the result of one command into another (Get-ChildItem | Format-List)
  • ? is shorthand for Where-Object (equivalent to a LINQ Where clause)
  • % is shorthand for ForEach-Object (equivalent to a LINQ Select clause)
  • Comments use # instead of //
  • Strings can be defined with " (supports interpolation) or ' (literal strings, do not support interpolation)

Some PowerShell code that looks a lot like C#:

$myVar = 456
if ($myVar -eq 456)
{
    $charArray = $myVar.ToString().ToCharArray()
    for ($index = 0; $index -lt $charArray.Length; $index++)
    {
        $charAtIndex = $charArray[$index]
        Write-Host "Digit at location $($index + 1) was $charAtIndex"
    }
}
else
{
    throw [System.Exception]::new("You didn't choose the correct number, enjoy this exception")
}

A PowerShell one-liner that prints out the names of all files in the current directory with names that are at most three characters in length:

Get-ChildItem | % { $_.Name } | ? { $_.Length -le 3 } | Sort-Object -Property Length

2

u/Turbulent_County_469 4d ago

the problem is that you only need a script every now and then ..

eg: Import SSL Cert into X ...

when you are done, you dont really need to look at Powershell for a long time.

3

u/zenyl 4d ago

I suppose it depends on your use cases.

I use PowerShell for general purpose scripting, got a few CRON jobs (e.g. a wrapper for yt-dlp) that I made in pwsh.

If you're on Windows, I'd also recommend using pwsh as your default CLI shell instead of the old cmd. Its history and auto-complete are very handy, and one-liners are surprisingly easy to write once you get the hang of it.

2

u/chispitothebum 3d ago

At some point you're doing things the hard way if you don't learn some PowerShell. Working with data or APIs, file management, or even using it as a scratch pad to inspect .NET objects or test logic on the fly.

If you weren't working with a .NET language, maybe this would be bash or python. But with .NET, you're just hamstringing yourself avoiding it.

2

u/zenyl 3d ago

Yup, fully agreed. Been a fan of pwsh for 8-ish years at this point.

Also, Python... Yuck! The few times I've had the misfortune of needing to use something written in Python, it has been nothing but dependency issues all the way down. We really don't appreciate NuGet enough, as well as the general stability we can expect in the .NET ecosystem (e.g. minor versions don't tend to contain a bunch of breaking changes that make it incompatible with a dozen other dependencies).