C# · STEP 1 · INTRO
C# · Intro to the language
C# 14 on .NET 10 (anything from .NET 8 up runs every block here): variables, input, conditionals, loops, lists, dictionaries and functions — each shown first in the JavaScript you know, then in C#.
What you will learn#
- Creating Variables in a New Language
- Conditionals in a New Language
- Looping in a New Language
- Collections in a New Language
- Writing Functions in a New Language
Getting Started#
Install the current .NET SDK from dotnet.microsoft.com/download (.NET 10 as of this writing, the long-term-support release; .NET 8 and up runs everything on this page). Then open a terminal and create a console project:
dotnet --version # 10.0.xdotnet new console -o hellocd hellodotnet run # Hello, World!Program.cs is a single line — Console.WriteLine("Hello, World!"); — because modern C# lets you write top-level statements: no class, no Main method, just code. The template also turns on implicit usings, so Console and List<T> work without using System; at the top (add that line if a tool you paste into complains).
To try a snippet without a project, save it as hello.cs and run dotnet run hello.cs. For an editor: VS Code with the C# Dev Kit extension.
Creating Variables#
How we did it in Javascript
// We create constant variables with the const keywordconst myConstant = 5;// We create re-assignable variables with the let keywordlet myVariable = "Hello World"; // We Printed Variables to the console using console.logconsole.log(myConstant);console.log(myVariable);How we do this in C#
// Every variable has a type, written before its nameconst int MyConstant = 5;string myVariable = "Hello World"; // var lets the compiler work the type out from the right-hand side (still static)var myNumber = 42; // Console.WriteLine prints a line; $"..." interpolates like a JS template stringConsole.WriteLine(MyConstant);Console.WriteLine($"{myVariable} {myNumber}");WHY: C# is statically typed — myVariable = 5; is a compile error because myVariable is a string. const is only for values known at compile time (numbers, strings, booleans).
Receiving Input#
In JavaScript in the browser, input comes from forms or prompt. In Node, reading from the terminal goes through the readline module; the promise-based version reads cleanly with await:
// Node: ask a question in the terminal and wait for the answerimport readline from "node:readline/promises";import { stdin as input, stdout as output } from "node:process"; const rl = readline.createInterface({ input, output });const name = await rl.question("Who are you? ");console.log(`Hey there ${name}!`);rl.close();How would we do that in C#?
// Console.Write prints without a newline, so the cursor waits on the same lineConsole.Write("What is your name? "); // ReadLine returns string? — null if the input stream is closedstring? input = Console.ReadLine(); Console.WriteLine($"Hey there {input}");ReadLine() always gives you a string. If you want a number, convert it: int.Parse(text), or int.TryParse(text, out int age), which returns false instead of throwing on bad input. The ? in string? is C#'s nullable marker: the value may be null, and the compiler warns if you treat it as though it can't be.
Conditionals#
If statements in Javascript
const num = 5; if (num > 3) { console.log("num is greater than 3");} else if (num > 1) { console.log("num is greater than 1");} else { console.log("num is 1 or less");}If statements in C#
int num = 5; if (num > 3){ Console.WriteLine("num is greater than 3");}else if (num > 1){ Console.WriteLine("num is greater than 1");}else{ Console.WriteLine("num is 1 or less");}Same keywords, same operators: ==, !=, <, >=, &&, ||, !. Two differences: the condition must be a real bool (if (num) does not compile — no truthy/falsy), and there is no === because == never coerces types.
While Loops#
In Javascript
let counter = 0; //This will loop 10 timeswhile (counter < 10) { console.log(counter); counter += 1;}In C#
int counter = 0; // this will loop 10 timeswhile (counter < 10){ Console.WriteLine(counter); counter += 1; // counter++ works too}C# also has the for loop you know from JavaScript, and foreach for walking a collection:
for (int i = 0; i < 10; i++){ Console.WriteLine(i);} foreach (string word in new[] { "a", "b", "c" }){ Console.WriteLine(word);}10 Minute Exercise#
Write the code to do the following:
- Loop 10 times starting the counter at 0
- On each loop if the counter is even print "it's even"
- If odd, print "meow" if the number is divisible by 3
- Otherwise print nothing
Collections#
In Javascript we have arrays and objects
const myArray = [1, 2, 3]; console.log(myArray); //logging the entire arrayconsole.log(myArray[0]); // logging an individual item const myObject = { cheese: "gouda", bread: "rye",}; console.log(myObject); //logging the entire objectconsole.log(myObject.cheese); // logging a property using dot notationconsole.log(myObject["bread"]); // logging a property using square bracket notationIn C# we use List<T> and Dictionary<TKey, TValue> (the <T> says what type goes inside)
// Create a new list of ints with a collection expressionList<int> myList = [1, 2, 3]; // Add and remove elementsmyList.Add(4);myList.Remove(2); Console.WriteLine(myList); // prints the type name, not the itemsConsole.WriteLine(string.Join(", ", myList)); // 1, 3, 4Console.WriteLine(myList[0]); // printing an individual itemConsole.WriteLine(myList.Count); // 3 // Create a new dictionary: string keys, string valuesDictionary<string, string> myObject = new(){ ["cheese"] = "gouda", ["bread"] = "rye",}; Console.WriteLine(myObject["cheese"]); // one value; a missing key throws KeyNotFoundExceptionConsole.WriteLine(myObject.ContainsKey("jam")); // False // TryGetValue looks up without throwingif (myObject.TryGetValue("bread", out string? bread)){ Console.WriteLine(bread); // rye}There is no dot access for dictionary keys (myObject.cheese is a compile error) — square brackets or TryGetValue only. Everything in a List<int> must be an int; mixed bags are what classes (tomorrow) are for. Plain arrays (int[] nums = [1, 2, 3];) are fixed-length, so List<T> is the everyday choice. ArrayList and Hashtable, which the 2021 version used, are the pre-generics collections and are not used in new code.
10 Minute Exercise#
Look up the List<T> methods and apply them to the following list.
List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];- How to find a list's length (
Count) - How to loop over a list (
foreach (int n in numbers)) - How to add and remove items from a list (
Add,Insert,Remove,RemoveAt)
Functions#
in Javascript
const addNums = (x, y) => { return x + y;}; console.log(addNums(5, 5));In C#
// use the functionConsole.WriteLine(AddNums(5, 5)); // A function declared at the top level is a local function: return type, name, typed parametersint AddNums(int x, int y){ return x + y;}The return type comes first (void if nothing is returned), every parameter has a type, and names are PascalCase. A local function can be declared before or after the line that calls it. One-expression functions can use the arrow form, and parameters can have defaults and be passed by name:
string Greet(string name, string greeting = "Hello") => $"{greeting}, {name}!"; Console.WriteLine(Greet("Arthur")); // Hello, Arthur!Console.WriteLine(Greet("Arthur", greeting: "Welcome")); // Welcome, Arthur!C#'s lambda (a, b) => a * b is the arrow function stored in a variable (type Func<int, int, int>). Inside a class (tomorrow) the same function is a method with an access modifier: public static int AddNums(int x, int y).
10 minute exercise#
Write the following functions
SubNumsthat takes two arguments and returns their differenceSayHellothat takes a name as an argument and says hello to that nameSayHelloAdvthat takes aDictionary<string, string>with a name and age key and prints "hello {name}, how does it feel to be {age} years old"Loopertakes one list as an argument, loops over the list and prints each item individually
Resources to Learn More#
- A tour of the C# language — the official overview; its tutorials cover everything on this page
- Top-level statements — why there is no
MaininProgram.cs - Collections —
List<T>,Dictionary<TKey, TValue>, arrays - Nullable reference types — what
string?means
See also