2008-11-15 32 views
26

Trong những ngày đầu của .NET, tôi tin có một thuộc tính bạn có thể trang trí một lớp học để chỉ định một thuộc tính mặc định.Thuộc tính mặc định trong VB.NET?

Theo một số bài viết tôi đã tìm thấy, điều này dường như đã được rút ra khỏi khung tại một thời điểm nào đó, bởi vì nó hơi khó hiểu và tôi có thể thấy trường hợp đó như thế nào.

Tuy nhiên, có cách nào khác để có được chức năng được cung cấp không?

Nó trông như thế này:

<DefaultProperty("Value")> _ 
Public Class GenericStat 
    ... 
    Public Property Value() As Integer 
     ... 
    End Property 
    ... 
End Class 

Điều này cho phép bạn làm Response.Write(MyObject) thay vì Response.Write(MyObject.Value) ... Đây không phải là một ví dụ cực kỳ phiền phức, nhưng trong một số bối cảnh hướng đối tượng phức tạp nó được một chút gớm ghiếc . Xin vui lòng cho tôi biết nếu có một cách tốt hơn.

Lưu ý: Tôi không tìm kiếm Từ khóa mặc định, chỉ có thể được sử dụng trên các thuộc tính có tham số.

Trả lời

28

Vâng, khung công tác .NET có khái niệm về thành viên mặc định. Các thành phần chính là lớp DefaultMemberAttribute và Type.GetDefaultMembers(). Trong VB.NET, xác định các thành viên mặc định là một phần của cú pháp ngôn ngữ:

Public Class Sample 
    Private mValue As Integer 
    Default Public ReadOnly Property Test(ByVal index As Integer) As Integer 
     Get 
     Return index 
     End Get 
    End Property 
    End Class 

Sử dụng nó như thế này:

Sub Main() 
    Dim s As New Sample 
    Console.WriteLine(s(42)) 
    Console.ReadLine() 
    End Sub 

Trình biên dịch thực hiện điều này bằng cách phát ra [DefaultMember] tự động.Tuy nhiên điều này có một hạn chế, tài sản phải có một đối số chỉ mục, đặc biệt để tránh sự mơ hồ của cú pháp. Hạn chế này không được thực thi khi chỉ định thuộc tính một cách rõ ràng:

<System.Reflection.DefaultMember("AnotherTest")> _ 
    Public Class Sample 
    Public ReadOnly Property AnotherTest() As Integer 
     Get 
     Return 42 
     End Get 
    End Property 
    End Class 

Nhưng thành viên mặc định đó chỉ có thể truy cập như ngôn ngữ mặc định cho phép cú pháp đó. Mà tôi không biết một ví dụ trong .NET, điều này đã được sử dụng trở lại trong những ngày COM, như VB6. Ngoài ra lý do cốt lõi đằng sau VB6 có từ khóa Set, nó giải quyết sự mơ hồ và nói "Tôi có nghĩa là đối tượng, không phải là tài sản mặc định của đối tượng". Chi tiết cú pháp rất đau đớn cho nhiều lập trình viên Visual Basic bắt đầu lúc đó.

C# có cùng quy tắc chính xác nhưng không cho phép cùng một loại linh hoạt. Bạn có thể đã nhìn thấy người lập chỉ mục trước:

public class Sample { 
    public int this[int index] { 
     get { return index; } 
    } 
    } 

Mã này cũng làm cho trình biên dịch xuất ra thuộc tính [DefaultMember]. Thuộc tính được đặt tên trong thuộc tính đó là "Item". Và đó là lý do tại sao bạn thấy lập chỉ mục được ghi lại và lập chỉ mục trong Thư viện MSDN dưới dạng "Mục".

+0

Nhận xét thú vị. Nó không giải quyết vấn đề của tôi, nhưng ít nhất nó mang lại cho tôi một số nền tảng về tình hình - cảm ơn! –

+0

Nếu nó không trả lời câu hỏi của bạn tại sao bạn đánh dấu nó là câu trả lời đúng? –

+1

Vì câu trả lời cho vấn đề của tôi là: bạn không thể làm được. Anh chàng này cung cấp giải thích tốt nhất về lý do tại sao nó không hoạt động. –

1

Có thuộc tính DefaultProperty để ví dụ của bạn phải chính xác, nhưng điều này dường như là dành cho các thành phần được sử dụng trong trình tải xuống Biểu mẫu Windows.

+0

Tôi thấy rằng, nhưng nó không có vẻ để làm những gì tôi đang tìm kiếm. –

+0

Mà là để nói, tôi thực sự đã thử nó ra và nó dường như không có tác động nào cả. :) –

+2

Có, DefaultProperty thực sự chỉ hữu ích cho một propertygrid và là những gì cho phép nó để xác định nếu giá trị hiện tại khác với giá trị mặc định. –

1

Bạn có thể ghi đè phương thức ToString để xuất Giá trị dưới dạng chuỗi sao cho khi bạn thực hiện Response.Write (MyObject), bạn sẽ nhận được cùng một hiệu ứng.

Public Overrides Function ToString() As String 
     Return Me.Value.ToString 
    End Function 

[EDIT] Bây giờ tôi hiểu rõ hơn, tại sao không chỉ cung cấp cách trực tiếp vào giá trị của các đối tượng chứa.

Public Class MyClass 
    Private m_Stats(100) As Stats ' or some other collection' 

    Public Property StatValue(ByVal stat_number As Integer) As _ 
     Integer 
     Get 
      Return m_Stats(stat_number) 
     End Get 
     Set(ByVal Value As Integer) 
      m_Stats(stat_number) = Value 
     End Set 
    End Property 
End Class 
+0

Ý tưởng thú vị - nếu tôi có thể nhận biến để xuất hiện dưới dạng một số nguyên hoặc một đối tượng, điều đó thậm chí còn tốt hơn ... –

+0

Trả lời.Write sẽ gọi ToString trên đối tượng khi ghi nó vào luồng phản hồi. – tvanfosson

+0

Tôi không thực sự thực hiện việc trả lời mặc dù - việc sử dụng thực tế giống như: thisObject.stats (stat.health) .value, xem không? xấu xí. –

1

Để trả lời câu hỏi của chính tôi, quá tải nhà điều hành dường như là một giải pháp thú vị ở đây.

Cuối cùng, nó không phù hợp.

Tôi đã kết thúc việc thêm vào khoảng 17 phương pháp 1 dòng, có nghĩa là rất nhiều chỗ cho lỗi. Quan trọng hơn là bạn không thể quá tải toán tử gán; tình trạng quá tải cho = chỉ dành cho kiểm tra bình đẳng.

Vì vậy, ngay cả với điều này, tôi không thể nói:

Dim x as Integer = MyObject.Stats(Stat.Health) ... Trong ví dụ này nó kéo các đối tượng, nhưng không chuyển nó sang một số nguyên, vì vậy tất nhiên kết quả là một ngoại lệ.

Điều tôi thực sự cần là thuộc tính mặc định cũ, nhưng tôi nghĩ những ngày đó đã kết thúc.

4

Không, đó đã được gỡ bỏ một cách rõ ràng từ VB 7.

Khi bạn có một chuỗi dài của thuộc tính mặc định, biết chính xác những gì sẽ được trả lại là khó khăn. Khi cả hai bc có phương thức Foo, thì a.Foo(1) có nghĩa là a.b.Foo(1) hoặc a.b.c.Foo(1)?

Đá thật là Set. Bằng cách giảm các thuộc tính mặc định, chúng cũng có thể thả từ khóa Set để gán đối tượng.

+0

C++ thực sự có một vấn đề tương tự do thực tế là 'toán tử ->' có thể bị quá tải: Nó sẽ luôn gọi nested 'operator ->' s cho đến khi nó tới một con trỏ thực hoặc một đối tượng không quá tải nó. –

5

Trong ví dụ này, nó kéo đối tượng, nhưng không chuyển đổi thành số nguyên.

Brian, tôi không thấy lý do tại sao hiệu ứng mong muốn của bạn không thể đạt được bằng cách sử dụng Widening Operator CType. Mã bạn đã hiển thị cho chúng tôi có thể được thực hiện để hoạt động. Tuy nhiên, hãy cẩn thận với các chuyển đổi tiềm ẩn. Chúng thường là không phải là một ý tưởng hay.

0

Bạn vẫn có thể sử dụng thuộc tính nếu bạn nhập System.ComponentModel.

Như những người khác đã đề cập, điều này không lý tưởng vì VB.Net thích rằng bạn sử dụng thuộc tính Mặc định. Tất nhiên, điều đó đi kèm với các điều kiện, điều này không thực sự hữu ích (yêu cầu một chỉ mục, chẳng hạn).

Nhưng nếu bạn sử dụng

Imports System.ComponentModel

nó cho phép bạn sử dụng thuộc tính trên lớp học của bạn.

8

Tôi đã tìm thấy rằng bạn có thể làm chính xác những gì mà áp phích ban đầu muốn sử dụng Widening Operator CType Điều này đã được đề cập ở trên nhưng không có nhiều chi tiết, vì vậy tôi hoàn toàn bỏ lỡ khi tôi đang cố gắng tìm câu trả lời cho câu hỏi này. Phương pháp này không xác định một thuộc tính mặc định, mỗi se, nhưng nó đạt được kết quả tương tự.

Public Class GenericStat 
    ... 
    Public Property Value() As Integer 
    ... 
    End Property 
    ... 
    'this could be overloaded if needed 
    Public Sub New(ByVal Value As Integer) 
     _Value = Value 
    End Sub 
    ' 
    Public Shared Widening Operator CType(ByVal val As Integer) As GenericStat 
     Return New GenericStat(val) 
    End Operator 
    ' 
    Public Shared Widening Operator CType(ByVal val As GenericStat) As Integer 
     Return val.Value 
    End Operator 
End Class 

Bây giờ

Dim MyObject as GenericStat 
MyObject = 123 

Dim Int as Integer 
Int = MyObject 

cả công việc mà không có sự .Value tài liệu tham khảo và không có một indexer như myobject(1)

+0

Thú vị, tôi sẽ phải thử nghiệm điều này! –

1

Hi John câu trả lời của bạn là rất hữu ích! Tôi đã thay đổi để sử dụng với bất kỳ loại nào, cảm ơn.

Public Class GenericStat(Of Ttype) 

Public Property Value As Ttype 
' 
Public Sub New() 

End Sub 
' 
'this could be overloaded if needed 
Public Sub New(ByVal Value As Ttype) 
    _Value = Value 
End Sub 
' 
Public Shared Widening Operator CType(ByVal val As Ttype) As GenericStat(Of Ttype) 
    Return New GenericStat(Of Ttype)(val) 
End Operator 
' 
Public Shared Widening Operator CType(ByVal val As GenericStat(Of Ttype)) As Ttype 
    Return val.Value 
End Operator 

End Class 

Và việc sử dụng:

Dim MyInteger As GenericStat(Of Integer) 
MyInteger = 123 

Dim Int As Integer 
Int = MyInteger 

Dim MyString As GenericStat(Of String) 
MyString = "MyValue" 

Dim Str As String 
Str = MyString 
2

Tôi đã tìm kiếm một câu trả lời cho một vấn đề tương tự và trong quá trình tôi stumbled trên này ở đây. Thực sự câu trả lời của John đã chỉ cho tôi theo hướng tôi cần phải đi. Và nó có thể giúp đỡ với câu hỏi ban đầu cũng như:

Vấn đề của tôi: tôi cần một cái gì đó mà tôi có thể sử dụng giống như một Integer

Dim myVal as Integer 
myVal = 15 
If myVal = 15 then 
    ... 
End If 

... và vân vân ... Tuy nhiên tôi cần điều bổ sung cũng

myVal.SomeReadOnlyProperty (as String) 
myVal.SomeOtherReadOnlyProperty (as Integer) 

(thực sự những thuộc tính chỉ đọc có thể là phương pháp cũng ...)
vv ... vì vậy, tôi thực sự cần một Object

012.

Tôi đã nghĩ đến phương pháp khuyến nông cho Integer (@ _ @) ... Tôi không muốn đi theo con đường đó ...

Tôi cũng nghĩ đến việc viết một "ReadOnlyPropertyOracle" như là một lớp riêng biệt và cung cấp cho nó phương pháp thích

GetSomeReadOnlyProperty(ByVal pVal as Integer) as String 
GetSomeOtherReadOnlyProperty(ByVal pVal as Integer) as Integer 

weeeell .... Điều đó sẽ làm việc nhưng nhìn khủng khiếp ...

Vì vậy, trong đến Hack John và bình luận Brian MacKay về khai thác: Kết hợp cả hai, mở rộng/thu hẹp chuyển đổi toán tử (để gán) và toán hạng so sánh rs cho ... cũng so sánh. Dưới đây là một phần của mã của tôi và nó làm những gì tôi cần:

'The first two give me the assignment operator like John suggested 
Public Shared Widening Operator CType(ByVal val As Integer) As MySpecialIntType 
    Return New MySpecialIntType(val) 
End Operator 

'As opposed to John's suggestion I think this should be Narrowing? 
Public Shared Narrowing Operator CType(ByVal val As MySpecialIntType) As Integer 
    Return val.Value 
End Operator 

'These two give me the comparison operator 
'other operators can be added as needed 
Public Shared Operator =(ByVal pSpecialTypeParameter As MySpecialIntType, ByVal pInt As Integer) As Boolean 
    Return pSpecialTypeParameter.Value = pInt 
End Operator 

Public Shared Operator <>(ByVal pSpecialTypeParameter As MySpecialIntType, ByVal pInt As Integer) As Boolean 
    Return pSpecialTypeParameter.Value <> pInt 
End Operator 

Vâng, đây vẫn sẽ là 1-2 chục một dòng định nghĩa toán tử nhưng hầu hết trong số đó là tầm thường với rất ít chỗ cho sai sót ;-) Vì vậy, điều này làm việc cho tôi ...

+0

Cảm ơn sự đóng góp ở đây! Có vẻ như bạn đã mở rộng ý tưởng của John, và để diễn giải những gì Hans nói về điều đó trong một câu trả lời khác, điều này có thể hoạt động nhưng đó là một chút của một hack! Về phần mình, tôi đã đi đến kết luận rằng nếu bạn phải làm việc chăm chỉ để làm cho nó xảy ra, chúng tôi đang thực sự làm việc chống lại C# và có lẽ nên tìm một cách khác. Nhưng nó là mát mẻ mà bạn tìm thấy một cách. –

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