Pattern Matching, Records & Reflection
Pattern Matching
C# 9+ Pattern Matching
// Type pattern
if (obj is Product product)
{
Console.WriteLine(product.Name);
}
// Switch expression
var message = obj switch
{
null => "Empty",
int i when i > 0 => "Positive",
int i => "Negative",
string s => $"String: {s}",
_ => "Unknown"
};
// Relational patterns (C# 9)
var category = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 70 => "C",
_ => "F"
};
Records (C# 9+)
Value Equality
public record Product(string Name, decimal Price);
// So sánh bằng giá trị, không phải reference
var p1 = new Product("Apple", 1.99m);
var p2 = new Product("Apple", 1.99m);
Console.WriteLine(p1 == p2); // True!
With Expression
var p1 = new Product("Apple", 1.99m);
var p2 = p1 with { Price = 2.99m }; // Tạo bản sao với Price mới
// Non-destructive mutation
Positional Records
public record Product(string Name, decimal Price);
// Constructor và Deconstruct tự động
var product = new Product("Apple", 1.99m);
var (name, price) = product;
Attributes & Reflection
Attributes (Thuộc tính)
Attributes cung cấp metadata cho code elements (classes, methods, properties, etc.).
// Built-in attributes
[Serializable]
public class Product { }
[Obsolete("Use NewMethod instead")]
public void OldMethod() { }
[Conditional("DEBUG")]
public void DebugLog(string message) { }
// Custom attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorAttribute : Attribute
{
public string Name { get; }
public string Version { get; set; }
public AuthorAttribute(string name)
{
Name = name;
}
}
// Sử dụng custom attribute
[Author("John Doe", Version = "1.0")]
public class Calculator
{
[Author("Jane Smith")]
public int Add(int a, int b) => a + b;
}
Common Built-in Attributes
| Attribute | Mục đích | Ví dụ |
|---|---|---|
[Serializable] | Cho phép object serialization | [Serializable] class Data |
[Obsolete] | Đánh dấu method/class deprecated | [Obsolete("Use v2")] |
[Conditional] | Chỉ compile khi symbol defined | [Conditional("DEBUG")] |
[DllImport] | Import native DLL function | [DllImport("user32.dll")] |
[Required] | Data validation (ASP.NET Core) | [Required] string Name |
[Range] | Value range validation | [Range(1, 100)] int Age |
Reflection
Reflection cho phép inspect và thao tác với types tại runtime.
using System.Reflection;
// Lấy Type information
Type type = typeof(Product);
Console.WriteLine($"Type: {type.Name}");
Console.WriteLine($"Namespace: {type.Namespace}");
Console.WriteLine($"Is Class: {type.IsClass}");
// Lấy properties
PropertyInfo[] properties = type.GetProperties();
foreach (var prop in properties)
{
Console.WriteLine($"Property: {prop.Name} ({prop.PropertyType.Name})");
}
// Lấy methods
MethodInfo[] methods = type.GetMethods();
foreach (var method in methods)
{
Console.WriteLine($"Method: {method.Name}");
}
// Kiểm tra attributes
var attributes = type.GetCustomAttributes(typeof(AuthorAttribute), false);
foreach (AuthorAttribute attr in attributes)
{
Console.WriteLine($"Author: {attr.Name}, Version: {attr.Version}");
}
Dynamic Type Creation & Invocation
// Tạo instance dynamically
Type calculatorType = typeof(Calculator);
object calculator = Activator.CreateInstance(calculatorType);
// Gọi method dynamically
MethodInfo addMethod = calculatorType.GetMethod("Add");
object result = addMethod.Invoke(calculator, new object[] { 5, 3 });
Console.WriteLine($"Result: {result}"); // 8
// Get/Set property values
PropertyInfo nameProperty = calculatorType.GetProperty("Name");
nameProperty.SetValue(calculator, "MyCalculator");
string name = (string)nameProperty.GetValue(calculator);
Performance Considerations
// ❌ Chậm - Reflection mỗi lần
for (int i = 0; i < 1000; i++)
{
MethodInfo method = obj.GetType().GetMethod("Process");
method.Invoke(obj, null);
}
// ✅ Tốt hơn - Cache MethodInfo
MethodInfo cachedMethod = obj.GetType().GetMethod("Process");
for (int i = 0; i < 1000; i++)
{
cachedMethod.Invoke(obj, null);
}
// ✅ Tốt nhất - Delegate (Expression Trees)
var method = obj.GetType().GetMethod("Process");
var delegate = (Action)Delegate.CreateDelegate(typeof(Action), obj, method);
for (int i = 0; i < 1000; i++)
{
delegate();
}
Use Cases cho Reflection
- Dependency Injection Frameworks - Tìm và register services
- ORM Frameworks - Map database columns to properties
- Serialization/Deserialization - Inspect object structure
- Testing Frameworks - Tìm và chạy test methods
- Plugin Systems - Load và instantiate plugins dynamically
C# 12 Features
Primary Constructors (C# 12)
public class Point(int X, int Y)
{
public int Sum() => X + Y;
}
var point = new Point(3, 4);
Console.WriteLine(point.Sum()); // 7
Collection Expressions
// Array
int[] numbers = [1, 2, 3, 4, 5];
// Span
Span<int> span = [1, 2, 3];
// List
List<string> names = ["Alice", "Bob"];
Default Lambda Parameters
Func<int, int, int> add = (int a, int b = 10) => a + b;
Console.WriteLine(add(5)); // 15
Alias Any Type
using IntList = List<int>;
using Point3D = (int x, int y, int z);