2009-05-20 38 views
15

Tôi chỉ đọc thông tin trên this page và khi mới? nhà điều hành được đề cập, nó khá không rõ ràng với tôi những gì sẽ sử dụng của nó được.
Mọi người có thể vui lòng cung cấp giải thích nhanh, đăng mã được mã của nhà điều hành này sử dụng và có thể đề cập đến trường hợp sử dụng không?
Chỉnh sửa: điều này thực sự khó xử, tôi đã nhận thấy rằng? nhà điều hành không còn được đề cập trong ghi chú phát hành của Don. Bất kỳ ý tưởng nào về lý do đó?Toán tử F # "?"

Trả lời

30

Có hai mới khai thác "đặc biệt" trong F # phiên bản này, và (<? -) (?). Chúng không được xác định, nhưng chúng có sẵn cho quá tải, vì vậy bạn có thể tự định nghĩa chúng. Bit đặc biệt là cách chúng xử lý toán hạng thứ hai của chúng: chúng yêu cầu nó phải là một định danh F # hợp lệ, nhưng chuyển nó cho hàm thực hiện toán tử như một chuỗi. Nói cách khác:

a?b 

được khử đường đến:

(?) a "b" 

và:

a?b <- c 

được khử đường đến:

(?<-) a "b" c 

Một định nghĩa rất đơn giản của những nhà khai thác có thể là:

let inline (?) (obj: 'a) (propName: string) : 'b = 
    let propInfo = typeof<'a>.GetProperty(propName) 
    propInfo.GetValue(obj, null) :?> 'b 

let inline (?<-) (obj: 'a) (propName: string) (value: 'b) = 
    let propInfo = typeof<'a>.GetProperty(propName) 
    propInfo.SetValue(obj, value, null) 

Lưu ý rằng kể từ khi kiểu trả về cho gettor là chung chung, bạn sẽ phải xác định nó ở trang web sử dụng trong hầu hết các trường hợp, ví dụ:

let name = foo?Name : string 

mặc dù bạn vẫn có thể chuỗi gọi (?) (kể từ số đầu tiên của (?) cũng là chung chung):

let len = foo?Name?Length : int 

khác, thú vị hơn, thực hiện là để tái sử dụng phương pháp CallByName cung cấp bởi VB:

open Microsoft.VisualBasic  

let inline (?) (obj: 'a) (propName: string) : 'b = 
    Interaction.CallByName(obj, propName, CallType.Get, null) :?> 'b //' 

let inline (?<-) (obj: 'a) (propName: string) (value: 'b) = 
    Interaction.CallByName(obj, propName, CallType.Set, [| (value :> obj) |]) 
    |> ignore 

Ưu điểm của việc đó là nó sẽ xử lý cả tài sản và các lĩnh vực một cách chính xác, làm việc với các đối tượng IDispatch COM vv

+1

Như một lưu ý phụ, rõ ràng, F # PowerPack bao gồm một thực hiện mặc định hợp lý. –

4

Có vẻ như "?" toán tử liên quan đến Thời gian chạy ngôn ngữ động (DLR). Tức là, bạn sử dụng nó khi bạn muốn liên kết với một thành viên đối tượng (phương thức, thuộc tính) trong thời gian chạy, thay vì ở thời gian biên dịch.

Thật buồn cười vì tôi đã hy vọng rằng đây sẽ là cách gọi thành viên năng động sẽ hoạt động trong C#. Than ôi, C# cho thấy chức năng này thông qua loại "giả" ("động" IIRC). Theo ý kiến ​​của tôi, điều này làm cho đoạn code ít rõ ràng hơn (bởi vì bạn phải theo dõi các khai báo biến để biết nếu cuộc gọi là sớm ràng buộc hoặc cuối ràng buộc).

Tôi không biết cú pháp chính xác, nhưng nếu tôi phải đoán, nó thay thế hoặc tăng thêm "." (dấu chấm) toán tử. Như trong:

let x = foo?Bar() 

hoặc có thể:

let x = foo.?Bar() 
+1

"vì bạn phải theo dõi khai báo biến để biết liệu cuộc gọi có bị ràng buộc sớm hay bị ràng buộc muộn" ... Bạn không phải theo dõi rất xa. động phải là biến cục bộ và không thể là thành viên loại; nếu bạn phải di chuyển rất xa để tìm hiểu xem một biến có động hay không, rất có thể bạn cần phải cấu trúc lại. Thêm vào đó IDE sẽ sẵn sàng cho bạn biết loại nếu bạn di chuột qua tên của một biến ... – Randolpho

+2

Điểm tốt. Đối với những gì nó có giá trị, có một lý do tôi muốn một nhà điều hành "cuộc gọi bị ràng buộc muộn" trong việc triển khai kiểu "động": Do có thể móc vào DLR bằng cách thực hiện một giao diện, tôi có thể tưởng tượng một kịch bản bạn muốn thực hiện các cuộc gọi bị ràng buộc sớm và các cuộc gọi bị ràng buộc trễ trên cùng một tham chiếu. –

+0

Vì tò mò nên chọn loại foo nào và tại sao tôi muốn làm điều đó thay vì foo.Bar()? Bên cạnh đó, tôi không thể đạt được kết quả tương tự thông qua phản ánh? – em70

1

Có một mô-đun FSharp.Interop.Dynamic, trên NuGet mà thực hiện các hành động bằng cách sử dụng DLR.

let ex1 = ExpandoObject() in 
ex1?Test<-"Hi"; 
ex1?Test |> should equal "Hi"; 

Nó mã nguồn mở, giấy phép Apache, bạn có thể nhìn vào implementation và nó bao gồm đơn vị kiểm tra example cases.

Các vấn đề liên quan