Three features give C# much of its character: delegates and lambdas for passing functions as values, LINQ for declarative queries, and async/await for waiting on I/O without tying up a thread. Each builds on the one before it.
Delegates and Lambdas
A delegate is a type-safe reference to a method. You can declare your own delegate types, but most code uses the built-in Func<...> (returns a value) and Action<...> (returns nothing). A lambda expression, (parameters) => expression, creates an anonymous method on the spot.
Func<int, int, int> add = (a, b) => a + b;
Func<string, bool> isLong = s => s.Length > 5;
Action<string> log = message => Console.WriteLine($"[log] {message}");
Console.WriteLine(add(2, 3)); // 5
Console.WriteLine(isLong("TASTEDEV")); // True
log("starting up");
// a method that takes another function as an argument
static List<int> Apply(List<int> items, Func<int, int> transform)
{
var result = new List<int>();
foreach (var item in items)
result.Add(transform(item));
return result;
}
var doubled = Apply([1, 2, 3], x => x * 2); // [2, 4, 6]
// lambdas can capture variables from the surrounding scope
int threshold = 10;
Func<int, bool> overThreshold = x => x > threshold;
Events build on delegates too: button.Click += (sender, e) => ... attaches a lambda to an event.
LINQ
LINQ (Language Integrated Query) gives you one consistent way to query arrays, lists, databases, and other data sources. The most common style is method syntax: chaining extension methods from System.Linq and passing lambdas to them.
List<Order> orders =
[
new("Ana", "Books", 18.00m),
new("Ben", "Electronics", 320.00m),
new("Ana", "Electronics", 45.00m),
new("Cai", "Books", 22.00m),
];
var bigOrders = orders
.Where(o => o.Amount >= 20m)
.OrderByDescending(o => o.Amount)
.Select(o => $"{o.Customer}: {o.Amount:F2}")
.ToList();
var byCategory = orders
.GroupBy(o => o.Category)
.Select(g => new { Category = g.Key, Total = g.Sum(o => o.Amount), Count = g.Count() });
foreach (var row in byCategory)
Console.WriteLine($"{row.Category}: {row.Count} orders, {row.Total:F2} total");
bool anyExpensive = orders.Any(o => o.Amount > 100m);
var first = orders.FirstOrDefault(o => o.Customer == "Cai");
record Order(string Customer, string Category, decimal Amount);
(With top-level statements, type declarations go last.) Query syntax reads more like SQL and compiles to the same method calls:
var query =
from o in orders
where o.Category == "Books"
orderby o.Amount
select o.Customer;
LINQ uses deferred execution: Where and Select only describe a query, which runs when you enumerate it or call , , or . Enumerating twice runs it twice, so call once if you will reuse the results.
0 commentaire
Se connecter · Connectez-vous pour laisser un commentaire.