Default properties in VB.NET?

2020-01-30 04:09发布

In the early days of .NET, I believe there was an attribute you could decorate a class with to specify a default property.

According to some articles I've found, this appears to have been yanked from the framework at some point, because it was a little confusing, and I can see how that is the case.

Still, is there another way to get the functionality it provided?

It looked something like this:

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

This allowed you to do Response.Write(MyObject) instead of Response.Write(MyObject.Value)... This is not a terribly clunky example, but in some complex object-oriented contexts it gets a little hideous. Please let me know if there is a better way.

Note: I am not looking for the Default keyword, which can only be used on properties that take a parameter.

标签: .net vb.net oop
10条回答
我只想做你的唯一
2楼-- · 2020-01-30 04:56

I've been looking for an answer to a similar problem and in the process I stumbled across this here. Actually John's answer pointed me into the direction I needed to go. And it might help with the original question as well:

My Problem: I needed something that I could use just like an Integer

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

...and so on... However I needed additional things as well

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

(actually those readonly Properties could be Methods as well ...)
etc... So I really needed an Object

I was thinking of extension methods for Integer ( @ _ @ ) ... I didn't want to go down that road ...

I also thought of writing a "ReadOnlyPropertyOracle" as a separate class and give it Methods like

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

weeeell .... That would have worked but looked gruesome ...

So in came John's Hack and Brian MacKay's comment about operators: Combining both, widening/narrowing conversion operators (for assignment) and comparison operators for ... well comparision. Here is part of my code and it does what I need:

'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

Yes, this will still be 1-2 dozen one-line operator definitions but most of them are trivial with little room for error ;-) So this works for me...

查看更多
叼着烟拽天下
3楼-- · 2020-01-30 04:56

Hi John your answer was very useful! I changed for use with any type, thanks.

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

And the usage:

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
查看更多
我想做一个坏孩纸
4楼-- · 2020-01-30 05:04

I've found that you can do exactly what the original poster wanted using Widening Operator CType This was mentioned above but without much detail, so I entirely missed it as I was trying to find an answer to this question. This methodology doesn't define a default property, per se, but it achieves the same result.

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

So now

Dim MyObject as GenericStat
MyObject = 123

and

Dim Int as Integer
Int = MyObject   

both work without the .Value reference and without an indexer such as myobject(1)

查看更多
劳资没心,怎么记你
5楼-- · 2020-01-30 05:04

You could override the ToString method to output Value as a string so that when you do Response.Write(MyObject), you get the same effect.

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

[EDIT] Now that I understand it better, why not just provide a way to get directly at the values of the contained objects.

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
查看更多
登录 后发表回答