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条回答
The star\"
2楼-- · 2020-01-30 04:41

No, that was explicitly removed from VB 7.

When you have a long chain of default properties, knowing exactly what will be returned is hard. When both b and c have a Foo method, does a.Foo(1) mean a.b.Foo(1) or a.b.c.Foo(1)?

The real kicker was Set. By dropping default properties, they were also able to drop the Set keyword for object assignment.

查看更多
smile是对你的礼貌
3楼-- · 2020-01-30 04:43

In this example it pulls the object, but does not convert it to an integer.

Brian, I don't see why your desired effect cannot be achieved using a Widening Operator CType. The code you showed us can be made to work. However, beware of implicit conversions. They're generally not a good idea.

查看更多
Luminary・发光体
4楼-- · 2020-01-30 04:45

Well, the .NET framework does have a notion of a default member. Key ingredients are the DefaultMemberAttribute class and Type.GetDefaultMembers(). In VB.NET, specifying the default member is part of the language syntax:

  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

Use it like this:

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

The compiler implements this by emitting [DefaultMember] automatically. This however has a restriction, the property must have an index argument, specifically to avoid the syntax ambiguity. This restriction is not enforced when specifying the attribute explicitly:

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

But that default member would only be accessible as a default by a language that allows such syntax. For which I don't know an example in .NET, this was used back in the COM days, like VB6. Also the core reason behind VB6 having the Set keyword, it solves the ambiguity and states "I mean the object, not the object's default property". Very painful syntax detail for many beginning Visual Basic programmers back then.

C# has the exact same rules, but doesn't allow the same kind of flexibility. You've probably seen the indexer before:

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

This code also makes the compiler output the [DefaultMember] attribute. The named property in that attribute is "Item". And that's why you see the indexer documented and indexed in the MSDN Library as "Item".

查看更多
走好不送
5楼-- · 2020-01-30 04:48

There is a DefaultProperty attribute so your example should be correct, but this seems to be for components which are used in the Windows Forms desinger.

查看更多
We Are One
6楼-- · 2020-01-30 04:49

To answer my own question, operator overloading seemed to be an interesting solution here.

In the end, it wasn't a good fit.

I ended up having to add in about 17 1-line methods, which meant lots of room for bugs. More important is that you can't overload the assignment operator; the overload for = is for equality testing only.

So even with this, I can't say:

Dim x as Integer = MyObject.Stats(Stat.Health) ...In this example it pulls the object, but does not convert it to an integer, so of course the result is an exception.

What I really need is a good old fashioned default property, but I think those days are over.

查看更多
戒情不戒烟
7楼-- · 2020-01-30 04:50

You can still use the attribute if you import System.ComponentModel.

As others mentioned, this is not ideal since VB.Net prefers that you use the Default attribute. Of course, that comes with conditions, which doesn't really help (requiring an index, for example).

But if you use

Imports System.ComponentModel

it allows you to use the attribute on your class.

查看更多
登录 后发表回答