Introduction
JavaScript and C# are powerhouse languages in the world of web development. JavaScript, the ubiquitous client-side scripting language, powers dynamic content on the web, while C#, a statically typed language developed by Microsoft, is primarily used for server-side applications with ASP.NET. Whether you're transitioning from one language to another or just curious about their similarities, this article will provide an in-depth look at the features they share.
Syntax and Basic Structures
Variables and Data Types
Both JavaScript and C# use similar syntax for declaring variables, but they handle data types differently. JavaScript is dynamically typed, meaning variable types are determined at runtime. C#, on the other hand, is statically typed, requiring explicit type declarations.
JavaScript
const number = 12; // Number
const name = "John"; // String
let isActive = true; // Boolean
let data = null; // Null
let nothing; // Undefined
const bigInt = 123456789012345678901234567890n; // BigInt
const symbol = Symbol('symbol'); // Symbol
const person = { name: "John", age: 27 }; // Object
const numbers = [1, 2, 3, 4, 5]; // Array
C#
int number = 12; // Integer
string name = "John"; // String
bool isActive = true; // Boolean
object data = null; // Null
// No direct equivalent for undefined, but null is used for similar purposes
long bigInt = 1234567890123456789; // BigInt equivalent in C# is typically 'long'
decimal preciseNumber = 1234567.89m; // Decimal for high precision
char letter = 'A'; // Character
var person = new { Name = "John", Age = 27 }; // Anonymous object
int[] numbers = { 1, 2, 3, 4, 5 }; // Array
Type Conversion
Both languages provide mechanisms for type conversion.
JavaScript
let num = "12";
let intNum = parseInt(num); // Converts to integer
let floatNum = parseFloat(num); // Converts to float
let boolVal = Boolean(num); // Converts to boolean (true)
C#
string num = "12";
int intNum = Int32.Parse(num); // Converts to integer
double floatNum = Double.Parse(num); // Converts to double
bool boolVal = Boolean.Parse(num); // Converts to boolean
Functions and Methods
Functions/methods in both languages can look quite similar, though C# requires explicit return types.
JavaScript
function greet(name) {
return `Hello, ${name}!`;
}
const greet = (name) => `Hello, ${name}!`;
C#
public string Greet(string name) {
return $"Hello, {name}!";
}
Objects and Classes
Object Literals
Creating objects using object literals is straightforward in both languages.
JavaScript
let person = {
name: "John",
age: 27,
greet: function() {
return `Hello, my name is ${this.name}`;
}
};
C#
var person = new {
Name = "John",
Age = 27,
Greet = new Func<string>(() => "Hello, my name is John")
};
Classes and Inheritance
Both languages support class-based object-oriented programming, including inheritance.
JavaScript
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, my name is ${this.name}`;
}
}
class Employee extends Person {
constructor(name, age, jobTitle) {
super(name, age);
this.jobTitle = jobTitle;
}
work() {
return `${this.name} is working as a ${this.jobTitle}`;
}
}
C#
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age) {
Name = name;
Age = age;
}
public string Greet() {
return $"Hello, my name is {Name}";
}
}
public class Employee : Person {
public string JobTitle { get; set; }
public Employee(string name, int age, string jobTitle) : base(name, age) {
JobTitle = jobTitle;
}
public string Work() {
return $"{Name} is working as a {JobTitle}";
}
}
Data Structures
Arrays
Arrays are fundamental data structures available in both languages.
JavaScript
let numbers = [1, 2, 3, 4, 5];
console.log(numbers[2]); // Output: 3
numbers.push(6); // Adds 6 to the end
numbers.unshift(0); // Adds 0 to the beginning
numbers.pop(); // Removes the last element
numbers.shift(); // Removes the first element
C#
int[] numbers = { 1, 2, 3, 4, 5 };
// Accessing elements
Console.WriteLine(numbers[2]); // Output: 3
// Arrays in C# are of fixed size, so typically use List<T> for dynamic arrays
List<int> numberList = new List<int> { 1, 2, 3, 4, 5 };
numberList.Add(6); // Adds 6 to the end
numberList.Insert(0, 0); // Add 0 to the beginning
numberList.RemoveAt(numberList.Count - 1); // Removes the last element
numberList.RemoveAt(0); // Removes the first element
Lists
JavaScript doesn't have a direct equivalent of List since arrays are already dynamic. Instead, it uses arrays for dynamic lists.
JavaScript
const numbers = [1, 2, 3, 4, 5];
numbers.push(6); // Adding an element
console.log(numbers[0]); // Output: 1
numbers.pop(); // Removes the last element
// Iterating over an array
numbers.forEach(number => console.log(number));
// or
for (let num of numbers) {
console.log(num);
}
In C#, lists are dynamic arrays provided by the List class.
C#
using System;
using System.Collections.Generic;
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
numbers.Add(6); // Adding an element
Console.WriteLine(numbers[0]); // Output: 1
numbers.RemoveAt(numbers.Count - 1); // Removes the last element
// Iterating over a list
foreach (int number in numbers) {
Console.WriteLine(number);
}
Sets
Sets are collections of unique values. JavaScript has the Set
object, and C# has the HashSet
.
JavaScript
const set = new Set([1, 2, 3, 4, 5]);
set.add(6); // Adding an element
console.log(set.has(3)); // Checking for an element
set.delete(4); // Removing an element
// Iterating over a set
for (const value of set) {
console.log(value);
}
C#
using System;
using System.Collections.Generic;
HashSet<int> set = new HashSet<int> { 1, 2, 3, 4, 5 };
set.Add(6); // Adding an element
Console.WriteLine(set.Contains(3)); // Checking for an element
set.Remove(4); // Removing an element
// Iterating over a set
foreach (int value in set) {
Console.WriteLine(value);
}
Stacks and Queues
Both languages provide stack and queue data structures.
JavaScript
// Stack using array
const stack = [];
stack.push(1); // Push
stack.push(2);
console.log(stack.pop()); // Pop, Output: 2
// Queue using array
const queue = [];
queue.push(1); // Enqueue
queue.push(2);
console.log(queue.shift()); // Dequeue, Output: 1
C#
using System;
using System.Collections.Generic;
// Stack
Stack<int> stack = new Stack<int>();
stack.Push(1); // Push
stack.Push(2);
Console.WriteLine(stack.Pop()); // Pop, Output: 2
// Queue
Queue<int> queue = new Queue<int>();
queue.Enqueue(1); // Enqueue
queue.Enqueue(2);
Console.WriteLine(queue.Dequeue()); // Dequeue, Output: 1
Asynchronous Programming
Promises and Async/Await
Both languages support asynchronous programming, though the mechanisms differ slightly.
JavaScript
async function fetchData() {
try {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
C#
public async Task FetchDataAsync() {
try {
HttpClient client = new HttpClient();
var response = await client.GetAsync("https://api.example.com/data");
var data = await response.Content.ReadAsStringAsync();
Console.WriteLine(data);
} catch (Exception ex) {
Console.WriteLine($"Error: {ex.Message}");
}
}
Error Handling
Error handling is straightforward in both languages using try-catch blocks.
JavaScript
try {
let result = riskyOperation();
} catch (error) {
console.error('An error occurred:', error);
}
C#
try {
var result = RiskyOperation();
} catch (Exception ex) {
Console.WriteLine($"An error occurred: {ex.Message}");
}
LINQ and Higher-Order Functions
Higher-order functions are functions that operate on other functions, either by taking them as arguments or by returning them. JavaScript’s functional programming capabilities make extensive use of higher-order functions.
JavaScript
const numbers = [1, 2, 3, 4, 5];
// map: applies a function to each element in the array
const squares = numbers.map(n => n * n);
console.log(squares); // Output: [1, 4, 9, 16, 25]
// filter: selects elements that satisfy a condition
const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // Output: [2, 4]
// reduce: combines elements to a single value
const sum = numbers.reduce((total, n) => total + n, 0);
console.log(sum); // Output: 15
// forEach: performs a function on each element
numbers.forEach(n => console.log(n));
LINQ (Language Integrated Query) is a powerful feature in C# that provides query capabilities directly in the language. LINQ can be used with arrays, collections, databases, XML, and more.
C#
using System;
using System.Linq;
using System.Collections.Generic;
int[] numbers = { 1, 2, 3, 4, 5 };
// Select (equivalent to map in JavaScript)
var squares = numbers.Select(n => n * n).ToArray();
Console.WriteLine(string.Join(", ", squares)); // Output: 1, 4, 9, 16, 25
// Where (equivalent to filter in JavaScript)
var evenNumbers = numbers.Where(n => n % 2 == 0).ToArray();
Console.WriteLine(string.Join(", ", evenNumbers)); // Output: 2, 4
// Aggregate (equivalent to reduce in JavaScript)
var sum = numbers.Aggregate(0, (total, n) => total + n);
Console.WriteLine(sum); // Output: 15
// foreach (method in LINQ)
numbers.ToList().ForEach(n => Console.WriteLine(n));
Delegates and Function References
Delegates in C# are type-safe function pointers that allow methods to be passed as parameters. They are used to define callback methods and implement event handling. Delegates can point to methods that match a specific signature.
C#
using System;
public class Program {
// Define a delegate
public delegate void GreetDelegate(string message);
// Method that matches the delegate signature
public static void Greet(string message) {
Console.WriteLine(message);
}
public static void Main() {
// Instantiate the delegate
GreetDelegate greetDel = new GreetDelegate(Greet);
// Invoke the delegate
greetDel("Hello, World!"); // Output: Hello, World!
// Using built-in Action delegate
Action<string> greetAction = Greet;
greetAction("Hello with Action!"); // Output: Hello with Action!
// Using built-in Func delegate
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 4)); // Output: 7
}
}
In JavaScript, functions are first-class citizens, meaning they can be assigned to variables, passed as arguments to other functions, and returned from functions. This allows for powerful functional programming patterns and callback mechanisms.
JavaScript
// Define a function
function greet(message) {
console.log(message);
}
// Assign the function to a variable
const greetReference = greet;
// Call the function via the reference
greetReference("Hello, World!"); // Output: Hello, World!
// Higher-order function that takes a function as an argument
function executeGreet(greetFn, message) {
greetFn(message);
}
// Pass the function reference
executeGreet(greet, "Hello with executeGreet!"); // Output: Hello with executeGreet!
// Using arrow functions as callbacks
const add = (a, b) => a + b;
console.log(add(3, 4)); // Output: 7
// Using built-in higher-order functions
const numbers = [1, 2, 3, 4, 5];
const squares = numbers.map(n => n * n);
console.log(squares); // Output: [1, 4, 9, 16, 25]
Events
JavaScript uses event listeners to handle events.
JavaScript
const button = document.createElement('button');
document.body.appendChild(button);
button.addEventListener('click', () => {
console.log('Button clicked!');
});
// Simulate a click event
button.click(); // Output: Button clicked!
C# provides robust event handling using delegates.
C#
public class Button {
public event EventHandler Click;
protected virtual void OnClick(EventArgs e) {
Click?.Invoke(this, e);
}
public void SimulateClick() {
OnClick(EventArgs.Empty);
}
}
public class Program {
public static void Main() {
Button button = new Button();
button.Click += (sender, e) => Console.WriteLine("Button clicked!");
button.SimulateClick(); // Output: Button clicked!
}
}
Lambda Expressions
JavaScript uses arrow functions for similar purposes.
JavaScript
const add = (a, b) => a + b;
console.log(add(5, 3)); // Output: 8
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens.join(', ')); // Output: 2, 4
C# supports lambda expressions for inline anonymous functions.
C#
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(5, 3)); // Output: 8
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evens = numbers.Where(n => n % 2 == 0).ToList();
Console.WriteLine(string.Join(", ", evens)); // Output: 2, 4
Modules
JavaScript uses ES6 modules to organize code.
JavaScript
// File: mathOperations.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
// File: main.js
import { add, subtract } from './mathOperations.js';
console.log(add(5, 3)); // Output: 8
console.log(subtract(5, 3)); // Output: 2
C# uses namespaces and assemblies to organize code into modules.
C#
// File: MathOperations.cs
namespace MyApp.MathOperations {
public class Calculator {
public int Add(int a, int b) {
return a + b;
}
public int Subtract(int a, int b) {
return a - b;
}
}
}
// File: Program.cs
using MyApp.MathOperations;
public class Program {
public static void Main() {
Calculator calculator = new Calculator();
Console.WriteLine(calculator.Add(5, 3)); // Output: 8
Console.WriteLine(calculator.Subtract(5, 3)); // Output: 2
}
}
Conclusion
As a JavaScript developer with some past experience in C#, I've always been curious about their similarities. Turns out, they share a lot! From data types to features like properties and delegates, the parallels are striking.
Discovering these similarities has felt like finding a long-lost twin. "You do that too? Cool!"
Remember, in the world of coding, every new language you learn adds a new tool to your toolkit. And who knows? You might even find that mastering another language isn’t as daunting as it seems when you realize how much you already know.
I hope sharing these insights helps other developers see the connections between languages. Whether you're into JavaScript, curious about C#, or both, I hope you found this useful.
Happy coding!
Top comments (0)