你能通过Struct / Class的构造函数命名属性吗?

时间:2016-01-05 19:34:54

标签: vb.net properties structure unions bit-fields

我已经在这个问题上做了一些调查,并且真的能够找到很多东西。事实上,我很确定我已经知道了这个问题的答案,但我会问,以防万一有一些我不知道的先进技术。 (具有相当高的概率)你能声明一个结构/类的属性的名称,或者至少通过某种构造函数重命名它们吗?

基本上,长话短说我试图创建一个有效地为你提供位域样式标志的联合结构,但是你可以在声明时指定标志的名称,使代码看起来更清晰。我知道你通过建立一个整数(char / double / whatever)和一个bitfield结构的联合在C中做同样的事情。我基本上可以这样做的事情:

    Public status as BitField({"PowerOn","Ready","Error",...})

基本结构如下:

    Public Structure (or Class) BitField
        Private _value as UInt16

        Public Property value as UInt16
            Get
                Return _value
            End Get
            Set(input as UInt16)
                _value = input
            End Set
        End Property

        Public Property bit0 As Boolean
            Get
                Return ((_value And &H1UI) > 0)
            End Get
            Set(input as Boolean)
                If input Then
                    _value = _value Or &H1UI
                Else
                    _value = _value And &HFFFEUI
                End If
            End Set
        End Property

     (and so on for bit 1 through 15)

        Public Sub New(ByVal names() As String)
            ...Something that redeclairs/renames/equates "bit0" with names(0)...

            ...Something that redeclairs/renames/equates "bit1" with names(1)...
            and so on

        End Sub
    End Structure/Class

之后我可以调用status.Error来获取或设置第三位,但如果我想,我可以将status.value与掩码进行比较以检查某个状态。

我的意思是我在C中知道你只是这样做:

    union {
        unsigned int value;
        struct {
            unsigned PowerOn:1;
            unsigned Ready:1;
            unsigned Error:1;
            ...
        };
    } status;

但是我希望得到同样水平的清洁度#34;在我的代码中,没有必要有一个巨大的声明,我必须复制,每次我想使用它时重写一半。

正如我在开始时所说的那样,我假设我已经离开了基地而没有办法做我在VB.Net中提出的建议,但是如果有人有任何想法的话我很乐意听到他们的声音。

1 个答案:

答案 0 :(得分:1)

您无法在运行时创建或重命名属性,因为编译器需要知道它们是什么。根据评论,这里有一种方法可以为每个创建一个具有不同含义或地图的不同BitSetter对象,并使用最少的新代码

Public Class BitSetter(Of T)
    Private value As UInt16
    Public Sub New(v As UInt16)
        value = v
    End Sub

    Public Sub SetBit(n As T, b As Boolean)
        ' do stuff
    End Sub

    Public Function GetBit(n As T) As Boolean
        ' do stuff
    End Function
End Class
  • 我不确定Boolean input param的原因是什么,但为了清楚起见,我会将其分解为自己的方法。
  • 如图所示,只能在创建新对象时指定基值。这可能是也可能不是一个好主意。 SetValue(n As UInt16)方法是设置它的另一种方法。
  • 开启Option Strict;像value = value Or &H1UI这样的代码包含一个隐式转换而不会编译。

使类通用(Of T)允许您为每个品种定义一组不同的语义:

Private Enum FooBits
    Flag
    [Error]
    Green
    '...
End Enum

Private Enum BarBits
    Red = 0
    Charm = 1
    Quark = 3
    Ziggy = 4
End Enum

如果您不知道,Flag将用于位(0),Error用于1等,因此请按顺序或明确。第二组给出了显式值,而不是定义不应该使用的[Reserved]之类的东西,它只是跳过该值,因此 cant 被使用。创建和使用它们:

' starting value of 3:
Dim fooB As New BitSetter(Of FooBits)(3)
Dim barB As New BitSetter(Of BarBits)(6)       ' value = 6

Dim b As Boolean
b = fooB.GetBit(FooBits.Error)

barB.SetBit(BarBits.Quark, True)

FooBits版本只允许FooBits Enum的成员使用其方法。类型是强制执行的,并且在代码中清楚使用了哪个位/项。尝试将BarBits的成员与fooB一起使用(使用Option Strict)将导致编译错误。它还会阻止传递幻数值:

barB.SetBit(2, True)

因此,对于每个新的部分或地图,您需要的唯一新代码是新的Enum集(和BitSetter实例)。

如果你想让它更简洁(例如b = barB.Get(BarBits.Ziggy)),你需要转义类中的方法名称,因为它们是关键字:

Public Sub [Set](n As T, b As Boolean)

Public Function [Get](n As T) As Boolean