Khi nó được biên dịch, có một sự khác biệt giữa:
delegate { x = 0; }
và
() => { x = 0 }
?
Khi nó được biên dịch, có một sự khác biệt giữa:
delegate { x = 0; }
và
() => { x = 0 }
?
Câu trả lời:
Câu trả lời ngắn gọn: không.
Câu trả lời dài hơn có thể không liên quan:
Func
hoặc Action
), bạn sẽ có một đại biểu ẩn danh.Chỉnh sửa: Đây là một số liên kết cho Biểu thức.
Tôi thích câu trả lời của Amy, nhưng tôi nghĩ tôi là người phạm tội. Câu hỏi cho biết, "Một khi nó được biên dịch" - điều này cho thấy cả hai biểu thức đã được biên dịch. Làm thế nào cả hai có thể biên dịch, nhưng với một được chuyển đổi thành một đại biểu và một thành một cây biểu thức? Đây là một mẹo khó - bạn phải sử dụng một tính năng khác của các phương thức ẩn danh; người duy nhất không được chia sẻ bởi các biểu thức lambda. Nếu bạn chỉ định một phương pháp vô danh mà không chỉ định một danh sách tham số ở tất cả nó là tương thích với bất kỳ loại đại biểu trở về khoảng trống và không có bất kỳ out
thông số. Được trang bị kiến thức này, chúng ta sẽ có thể xây dựng hai tình trạng quá tải để làm cho các biểu thức hoàn toàn rõ ràng nhưng rất khác nhau.
Nhưng tai họa ập đến! Ít nhất là với C # 3.0, bạn không thể chuyển đổi biểu thức lambda với thân khối thành biểu thức - bạn cũng không thể chuyển đổi biểu thức lambda bằng một phép gán trong thân (ngay cả khi nó được sử dụng làm giá trị trả về). Điều này có thể thay đổi với C # 4.0 và .NET 4.0, cho phép thể hiện nhiều hơn trong cây biểu thức. Vì vậy, nói cách khác, với các ví dụ MojoFilter đã đưa ra, cả hai sẽ hầu như luôn được chuyển đổi thành cùng một thứ. (Thêm chi tiết trong một phút.)
Chúng ta có thể sử dụng thủ thuật tham số ủy nhiệm nếu chúng ta thay đổi phần thân một chút:
using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
int x = 0;
Foo( () => x );
Foo( delegate { return x; } );
}
static void Foo(Func<int, int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
static void Foo(Expression<Func<int>> func)
{
Console.WriteLine("I suspect the lambda expression...");
}
}
Nhưng chờ đã! Chúng ta có thể phân biệt giữa hai loại ngay cả khi không sử dụng cây biểu thức, nếu chúng ta đủ tinh ranh. Ví dụ dưới đây sử dụng quy tắc giải quyết quá tải (và thủ thuật khớp đại biểu ẩn danh) ...
using System;
using System.Linq.Expressions;
public class Base
{
public void Foo(Action action)
{
Console.WriteLine("I suspect the lambda expression...");
}
}
public class Derived : Base
{
public void Foo(Action<int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
}
class Test
{
static void Main()
{
Derived d = new Derived();
int x = 0;
d.Foo( () => { x = 0; } );
d.Foo( delegate { x = 0; } );
}
}
Ôi. Hãy nhớ rằng trẻ em, mỗi khi bạn quá tải một phương thức được kế thừa từ một lớp cơ sở, một chú mèo con bắt đầu khóc.
delegate { ... }
là không giống như delegate() { ... }
- sau này là chỉ tương thích với một loại parameterless đại biểu.
Trong hai ví dụ trên không có sự khác biệt, không.
Cách diễn đạt:
() => { x = 0 }
là một biểu thức Lambda với phần thân câu lệnh, vì vậy nó không thể được biên dịch thành một cây biểu thức. Trong thực tế, nó thậm chí không biên dịch vì nó cần một dấu chấm phẩy sau 0:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Amy B đúng. Lưu ý rằng có thể có những lợi thế khi sử dụng cây biểu thức. LINQ to SQL sẽ kiểm tra cây biểu thức và chuyển đổi nó thành SQL.
Bạn cũng có thể chơi các thủ thuật với lamdas và cây biểu thức để chuyển hiệu quả tên của các thành viên trong lớp vào một khung theo cách tái cấu trúc an toàn. Moq là một ví dụ về điều này.
Có một sự khác biệt
Thí dụ:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Và tôi thay thế bằng lambda: (lỗi)
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Một số điều cơ bản ở đây.
Đây là một phương pháp ẩn danh
(string testString) => { Console.WriteLine(testString); };
Vì các phương thức ẩn danh không có tên, chúng ta cần một đại biểu trong đó chúng ta có thể gán cả hai phương thức hoặc biểu thức này. ví dụ
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
Tương tự với biểu thức lambda. Thông thường chúng ta cần một đại biểu để sử dụng chúng
s => s.Age > someValue && s.Age < someValue // will return true/false
Chúng ta có thể sử dụng một đại biểu func để sử dụng biểu thức này.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);