Variables & Type Inference
Both languages support type inference, but Dart uses var, final, and const differently than C#.
C#
// C# variable declarations
var name = "John";
string title = "Developer";
const int MaxUsers = 100;
readonly DateTime created;
// Nullable reference types
string? optionalName = null;
Dart
// Dart variable declarations
var name = 'John';
String title = 'Developer';
const int maxUsers = 100;
final DateTime created;
// Null safety built-in
String? optionalName = null;
Key differences
- Dart uses
finalfor runtime constants (like C#readonly). - Dart's
constis compile-time only (like C#const). - Dart has built-in null safety with the
?operator. - Single quotes are preferred for strings in Dart.
Functions & Methods
Dart has arrow syntax, named parameters, and optional parameters similar to C#.
C#
// C# methods
public int Add(int a, int b) {
return a + b;
}
// Expression body
public int Multiply(int a, int b)
=> a * b;
// Optional and named parameters
public void Greet(
string name,
string greeting = "Hello"
) {
Console.WriteLine($"{greeting}, {name}");
}
Dart
// Dart functions
int add(int a, int b) {
return a + b;
}
// Arrow syntax
int multiply(int a, int b) => a * b;
// Named and optional parameters
void greet({
required String name,
String greeting = 'Hello',
}) {
print('$greeting, $name');
}
Key differences
- Dart uses
{ }for named parameters andrequiredfor mandatory named params. - Arrow syntax
=>works the same way. - Dart uses
$for string interpolation (similar to C#).
Classes & Objects
Both languages are object-oriented with similar class structures and inheritance models.
C#
// C# class
public class Person {
public string Name { get; set; }
public int Age { get; private set; }
public Person(string name, int age) {
Name = name;
Age = age;
}
public void SayHello() {
Console.WriteLine(
$"Hi, I'm {Name}"
);
}
}
Dart
// Dart class
class Person {
String name;
int _age;
Person(this.name, this._age);
// Named constructor
Person.guest()
: name = 'Guest', _age = 0;
void sayHello() {
print("Hi, I'm $name");
}
int get age => _age;
}
Key differences
- Dart uses
this.propertyshorthand in constructors. - Private members use underscore prefix (e.g.
_age). - Dart supports named constructors (e.g.
Person.guest). - Getters use the
getkeyword instead of properties.
Async Programming
Both languages use async/await pattern for asynchronous operations.
C#
// C# async/await
public async Task<string> FetchDataAsync() {
var client = new HttpClient();
var response = await client
.GetStringAsync(url);
return response;
}
// Using the async method
var data = await FetchDataAsync();
// Task.WhenAll
await Task.WhenAll(
task1,
task2,
task3
);
Dart
// Dart async/await
Future<String> fetchData() async {
final client = HttpClient();
final response =
await client.get(url);
return response;
}
// Using the async function
final data = await fetchData();
// Future.wait
await Future.wait([
task1,
task2,
task3,
]);
Key differences
- Dart uses
Future<T>instead ofTask<T>. Future.waitis equivalent toTask.WhenAll.Streamis equivalent toIAsyncEnumerable.asynckeyword is the same in both languages.
ORM & Database Access
Dart has several ORM solutions. Drift (formerly Moor) is the most popular, offering similar features to Entity Framework.
C#
// Entity Framework with C#
public class AppDbContext : DbContext {
public DbSet<User> Users { get; set; }
public DbSet<Post> Posts { get; set; }
}
public class User {
public int Id { get; set; }
public string Name { get; set; }
public List<Post> Posts { get; set; }
}
// Querying
var users = await context.Users
.Include(u => u.Posts)
.Where(u => u.Name.Contains("John"))
.ToListAsync();
// Adding
context.Users.Add(new User {
Name = "Jane"
});
await context.SaveChangesAsync();
Dart
// Drift ORM for Dart
@DriftDatabase(tables: [Users, Posts])
class AppDatabase extends _$AppDatabase {
AppDatabase() : super(_openConnection());
}
class Users extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text()();
}
// Querying
final users = await (select(users)
..where((u) => u.name.contains('John')))
.join([
leftOuterJoin(posts,
posts.userId.equalsExp(users.id))
]).get();
// Adding
await into(users).insert(
UsersCompanion(name: Value('Jane'))
);
Key differences
- Drift uses code generation like EF Core.
- Supports migrations, transactions, and relations.
- Type-safe queries with compile-time checking.
- Alternatives: Floor (Room-like), Isar (NoSQL).
- For Firebase: use
cloud_firestorepackage. - For simple key-value: use
shared_preferencesor Hive.
Null Safety
Dart has sound null safety built into the type system, similar to C# nullable reference types.
C#
// C# nullable types
string? name = null;
int? age = null;
// Null checking
if (name != null) {
Console.WriteLine(name.Length);
}
// Null-coalescing
var displayName = name ?? "Unknown";
// Null-conditional
var length = name?.Length ?? 0;
Dart
// Dart nullable types
String? name = null;
int? age = null;
// Null checking
if (name != null) {
print(name.length);
}
// Null-coalescing
final displayName = name ?? 'Unknown';
// Null-aware operators
final length = name?.length ?? 0;
Key differences
- Both use
?for nullable types. - Both use
??for null-coalescing. - Both use
?.for null-conditional access. - Dart's null safety is enforced at compile time.
Collections & LINQ
Dart has similar collection types and functional operations like C# LINQ.
C#
// C# collections
var numbers = new List<int>
{ 1, 2, 3, 4, 5 };
var names = new[]
{ "Alice", "Bob" };
// LINQ operations
var evens = numbers
.Where(n => n % 2 == 0)
.ToList();
var doubled = numbers
.Select(n => n * 2)
.ToList();
// Dictionary
var dict = new Dictionary<string, int>();
Dart
// Dart collections
final numbers = [1, 2, 3, 4, 5];
final names = ['Alice', 'Bob'];
// Collection operations
final evens = numbers
.where((n) => n % 2 == 0)
.toList();
final doubled = numbers
.map((n) => n * 2)
.toList();
// Map (Dictionary)
final map = <String, int>{};
Key differences
- Dart uses
[]for List, C# usesList<T>. where()is likeWhere(),map()is likeSelect().- Dart's
Mapis like C#Dictionary. - Dart has built-in collection literals with type inference.
Ready to learn more? Visit the Dart Guides or Flutter Docs.