2010-02-25 40 views
6

lại ở trường, chúng tôi đã viết một trình biên dịch mà dấu ngoặc nhọn có hành vi mặc định thực hiện tất cả các biểu thức, và trở về giá trị cuối cùng ... vì vậy bạn có thể viết một cái gì đó như:C# Phạm vi điều hành

int foo = { printf("bar"); 1 }; 

Có một cái gì đó tương đương trong C#? Ví dụ, nếu tôi muốn viết một hàm lambda có tác dụng phụ.

Điểm ít là về tác dụng phụ lambda (chỉ là ví dụ), nhiều hơn nếu có chức năng này ... ví dụ trong lisp, bạn có progn

Trả lời

7

Về nguyên tắc, câu trả lời từ Vlad là đúng và bạn không cần phải khai báo hàm lambda như một đại biểu trước. Ngoại trừ, tình hình không đơn giản trong C#, bởi vì trình biên dịch không thể quyết định xem biểu thức lambda cú pháp có được biên dịch như một đại biểu (ví dụ Func<int>) hay một cây biểu thức (ví dụ Expression<Func<int>>) và cũng có thể loại đại biểu tương thích khác. Vì vậy, bạn cần phải tạo ra các đại biểu:

int foo = new Func<int>(() => { 
    Console.WriteLine("bar"); return 1; })(); 

Bạn có thể đơn giản hóa mã hơi bằng cách định nghĩa một phương pháp mà chỉ đơn giản trả về các đại biểu và sau đó gọi phương thức - các biên dịch C# sẽ suy ra các loại đại biểu tự động:

static Func<R> Scope<R>(Func<R> f) { return f; } 

// Compiler automatically compiles lambda function 
// as delegate and infers the type arguments of 'Scope' 
int foo = Scope(() => { Console.WriteLine("bar"); return 1; })(); 

Tôi đồng ý rằng đây là mẹo lừa đảo không nên sử dụng :-), nhưng thực tế thú vị là có thể thực hiện được!

7

Có gì ngăn cản bạn từ việc có tác dụng phụ trong là một biểu thức lambda.

Func<int> expr =() => 
{ 
    Console.WriteLine("bar"); 
    return 1; 
}; 
int foo = expr(); 
5
int foo = (() => { printf("bar"); return 1; })(); 

Edit: cảm ơn cho bài phê bình mang tính xây dựng, nó nên được

int i = ((Func<int>)(() => { printf("bar"); return 1; }))(); 
+5

Đây là câu trả lời đúng - nói rằng, nghiêm túc xem xét không làm điều này. –

+2

Bạn có thể thực sự muốn kiểm tra xem mã có biên dịch trước khi bỏ phiếu hay không. Điều này không. -1. – Aaronaught

+0

Có, có, 'printf' không tồn tại trong C#. Nhưng câu trả lời không phải là về điều đó. – Vlad

3

Chúng tôi đã cân nhắc tạo cú pháp ngắn hơn ()=>{M();} để định nghĩa lambda, nhưng chưa thực sự tìm cú pháp mà cả hai đọc độc đáo và không dễ bị nhầm lẫn với khối, bộ sưu tập/khởi tạo đối tượng, hoặc khởi tạo mảng. Bạn đang mắc kẹt với cú pháp lambda cho bây giờ.