Tổng quan
Từ khóa is dùng để kiểm tra kiểu (type checking) và pattern matching. Trả về bool.
1. Type Checking Cơ bản
object obj = "Hello";
if (obj is string)
{
Console.WriteLine("Là string");
}
// Kết hợp với declaration pattern (C# 7+)
if (obj is string s)
{
Console.WriteLine($"String length: {s.Length}"); // s có scope trong if block
}
2. Pattern Matching Nâng cao (C# 7+)
Declaration Pattern
object obj = 42;
if (obj is int i)
{
Console.WriteLine($"Int: {i * 2}"); // 84
}
// Scope: biến 'i' chỉ tồn tại trong if block
Constant Pattern
object obj = 5;
if (obj is 5)
{
Console.WriteLine("Equals 5");
}
if (obj is null)
{
Console.WriteLine("Is null");
}
Var Pattern (Luôn true, gán vào biến)
object obj = "Test";
if (obj is var x)
{
Console.WriteLine(x.GetType().Name); // String
}
// Tương đương: var x = obj;
Property Pattern (C# 8+)
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
}
class Address
{
public string City { get; set; }
}
var person = new Person { Name = "John", Age = 25, Address = new Address { City = "Hanoi" } };
// Kiểm tra property
if (person is { Age: >= 18, Name: "John" })
{
Console.WriteLine("Adult John");
}
// Nested property pattern
if (person is { Address: { City: "Hanoi" } })
{
Console.WriteLine("From Hanoi");
}
Tuple Pattern (C# 8+)
var point = (X: 10, Y: 20);
if (point is (10, 20))
{
Console.WriteLine("Origin point");
}
if (point is (var x, var y))
{
Console.WriteLine($"({x}, {y})");
}
Type Pattern với When Clause (C# 7+)
object obj = "Hello";
if (obj is string s && s.Length > 5) // C# 7: is + when
if (obj is string s when s.Length > 5) // C# 7 syntax
{
Console.WriteLine($"Long string: {s}");
}
3. is not Pattern (C# 9+)
object obj = "Hello";
if (obj is not null)
{
Console.WriteLine("Not null");
}
if (obj is not string)
{
Console.WriteLine("Not a string");
}
// Kết hợp
if (obj is string s and not null)
{
// s guaranteed non-null string
}
4. Switch Expression với is (C# 8+)
object obj = 42;
string result = obj switch
{
int i when i > 0 => $"Positive int: {i}",
int i when i < 0 => $"Negative int: {i}",
int _ => "Zero",
string s => $"String: {s}",
null => "Null",
_ => "Unknown"
};
Console.WriteLine(result); // Positive int: 42
5. is vs as vs GetType()
| Toán tử | Mục đích | Trả về | Null handling |
|---|---|---|---|
is | Kiểm tra kiểu + pattern matching | bool | An toàn (false nếu null) |
as | Safe cast | Type hoặc null | Trả null nếu fail |
GetType() | Lấy Type runtime chính xác | Type object | Throw nếu null |
typeof() | Lấy Type compile-time | Type object | Static |
// is - kiểm tra
if (obj is string s) { /* use s */ }
// as - cast an toàn
string s = obj as string;
if (s != null) { /* use s */ }
// GetType - exact type (không tính inheritance)
if (obj.GetType() == typeof(string)) { } // Chỉ true nếu chính xác string
// typeof - compile-time type
if (typeof(string).IsAssignableFrom(obj.GetType())) { } // Polymorphic check
6. Generic Type Checking
public void Process(T item)
{
// Kiểm tra generic type
if (item is IEnumerable intList)
{
Console.WriteLine($"List of ints: {intList.Count()}");
}
// Kiểm tra interface
if (item is IDisposable disposable)
{
disposable.Dispose();
}
}
7. Performance Tips
isvới pattern matching compile thành code hiệu quả (không double-check).- Tránh
obj.GetType() == typeof(T)trong hot path - dùngis T. as+ null check nhanh hơnis+ cast riêng biệt (trước C# 7). Từ C# 7,is T vartối ưu tương đương.
Ví dụ thực tế: Visitor Pattern với Pattern Matching
abstract class Shape { }
class Circle : Shape { public double Radius { get; set; } }
class Rectangle : Shape { public double Width { get; set; } public double Height { get; set; } }
class Triangle : Shape { public double Base { get; set; } public double Height { get; set; } }
double GetArea(Shape shape) => shape switch
{
Circle c => Math.PI * c.Radius * c.Radius,
Rectangle r => r.Width * r.Height,
Triangle t => 0.5 * t.Base * t.Height,
_ => throw new ArgumentException("Unknown shape")
};