2010-07-12 30 views
34

Tôi có thể tạo Phương thức tiện ích mở rộng cho tất cả các lớp con của System.Object (mọi thứ) không?VB.NET: không thể sử dụng Phương pháp mở rộng trên ví dụ System.Object

Ví dụ:

<Extension> 
Public Function MyExtension(value As Object) As Object 
    Return value 
End Function 

Các chức năng trên sẽ không làm việc cho trường hợp đối tượng:

Dim myObj1 As New Object() 
Dim myObj2 = myObj1.MyExtension() 

Trình biên dịch không chấp nhận nó, là vấn đề trong máy tính của tôi? :)

CẬP NHẬT
Vấn đề dường như chỉ xảy ra trong VB, nơi các thành viên của đối tượng đang nhìn-up bằng cách phản xạ (late-bound).

CẬP NHẬT SAU TRẢ LỜI
FYI, như vb có một lợi thế mà C# thiếu có nghĩa là, các thành viên của Modules nhập khẩu được nhập khẩu với phạm vi toàn cầu, do đó bạn vẫn có thể sử dụng chức năng này mà không cần wrapper của họ:

Dim myObj2 = MyExtension(myObj1) 

Trả lời

8

Bạn không thể trực tiếp viết một phương pháp mở rộng cho đối tượng, nhưng sử dụng Generics bạn có thể đạt được kết quả tương tự:

<Extension()> 
Public Function NullSafeToString(Of T)(this As T) As String 
    If this is Nothing Then 
     Return String.Empty 
    End If 
    Return this.ToString() 
End Function 

Lưu ý rằng bạn có thể gọi đây là một phương pháp mở rộng trên tất cả mọi thứ trừ điều được khai báo có kiểu Object. Đối với những người, bạn phải hoặc gọi nó trực tiếp (đánh lừa bằng chứng) hoặc gọi qua đúc (mà có thể thất bại, vì không có giao diện univesal, do đó, hơi chancy).

-1

Chắc chắn bạn có thể, mặc dù bạn có thể muốn được tiết kiệm về những gì bạn làm ở đây để không làm lộn xộn mọi đối tượng. Một phương thức mở rộng mà tôi thích sử dụng cho Object là một phương thức được gọi là IsIn() có chức năng tương tự như câu lệnh SQL IN(). Thật tuyệt khi nói những câu như:

If someString.IsIn("a", "b", "c") Then 
    DoSomething() 
Else If someInt.IsIn(1, 2, 3) Then 
    DoSomethingElse() 
Else If someObj.IsIn(1, "q", #7/1/2010#) Then 
    DoSomethingTheThirdWay() 
End If 

EDIT -

gia tăng thực hiện ISIN() phương pháp khuyến nông dưới đây để giúp commenter.

Imports System.Runtime.CompilerServices 

Public Module ObjectExtensions 
    <Extension()> 
    Public Function IsIn(obj As Object, ParamArray values() As Object) As Boolean 
    For Each val As Object In values 
     If val.Equals(obj) Then Return True 
    Next 
    Return False 
    End Function 
End Module 
+2

Bạn có kiểm tra mã này? Dòng thứ ba (someObj) không hoạt động đối với tôi. – Shimmy

+0

Có, điều này phù hợp với tôi. Bạn đã viết phiên bản của phương thức mở rộng IsIn() như thế nào? Tôi đã chỉnh sửa bài đăng của mình để bao gồm việc triển khai để giúp bạn. – mattmc3

+4

Nếu bạn gõ 'someObj' làm' Object' trong mã của bạn, thì điều này chắc chắn sẽ * không * làm việc cho bạn. –

36

Nó có vẻ như không hỗ trợ phương pháp mở rộng về đối tượng được một quyết định thiết kế trong VB.

As a result, the only way we could prevent extension methods from completely breaking existing late bound code was to prevent them from being used on anything typed as object.

http://blogs.msdn.com/b/vbteam/archive/2007/01/24/extension-methods-and-late-binding-extension-methods-part-4.aspx

+1

Câu trả lời chính xác cho việc cung cấp liên kết nguồn của Microsoft. – Shimmy

12

Xem this question I asked some time ago. Về cơ bản, bạn có thểmở rộngObject trong VB.NET nếu bạn muốn; nhưng vì lý do tương thích ngược, không có biến số được khai báoObject sẽ có thể sử dụng phương pháp tiện ích mở rộng của bạn. Điều này là do VB.NET hỗ trợ kết buộc muộn trên Object, do đó, một nỗ lực truy cập vào một phương thức mở rộng sẽ bị bỏ qua có lợi cho việc cố gắng tìm một phương thức cùng tên từ loại đối tượng được đề cập.

Vì vậy, hãy mở rộng phương pháp này, ví dụ:

<Extension()> 
Public Sub Dump(ByVal obj As Object) 
    Console.WriteLine(obj) 
End Sub 

phương pháp Phần mở rộng này có thể được sử dụng ở đây:

' Note: here we are calling the Dump extension method on a variable ' 
' typed as String, which works because String (like all classes) ' 
' inherits from Object. ' 
Dim str As String = "Hello!" 
str.Dump() 

Nhưng không phải ở đây:

' Here we attempt to call Dump on a variable typed as Object; but ' 
' this will not work since late binding is a feature that came before ' 
' extension methods. ' 
Dim obj As New Object 
obj.Dump() 

Hãy tự hỏi mình tại sao mở rộng các phương thức không hoạt động trên các biến số dynamic trong C# và bạn sẽ nhận ra giải thích là giống nhau.

1

jmoreno's answerkhông thể được sử dụng với Option Strict On - nó throws lỗi:

BC30512 Option Strict On disallows implicit conversions from 'Object' to 'Integer'.

Nó cần chuyển đổi bối cảnh từ lớp để mô-đun mở rộng:

Dim text1 As String = MyExtModule.NullSafeToString(DataGridView1.Rows(0).Cells(0).Value) 
Các vấn đề liên quan