您可以通过 Struct's/Class 的构造函数命名属性吗?
Can you name properties through a Struct's/Class's constructor?
我已经就此主题进行了一些研究,但并没有真正找到太多相关内容。事实上,我很确定我已经知道这个问题的答案,但我还是要问,以防万一有一些我不知道的高级技术。 (有相当高的概率)你能声明结构的名称吗?s/class 的属性或至少通过某种构造函数重命名它们?
基本上,长话短说,我正在尝试创建一个联合结构,它可以有效地为您提供位域样式标志,但使您能够在声明时为标志指定名称,以使代码看起来更简洁。我知道您在 C 语言中做同样的事情,将一个整数 (char/double/whatever) 和一个位域结构结合起来。我基本上可以做到这一点:
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;
但我想在我的代码中获得相同级别的 "cleanliness",而不必有一个巨大的声明,每次我想使用它时都必须复制并重写一半。
就像我一开始说的,我假设我偏离了基地并且没有办法做我在 VB.Net 中提出的建议,但如果有人有任何想法,我'我很想听他们说。
您不能在运行时创建或重命名属性,因为编译器需要知道它们是什么。根据评论,这是一种使用最少的新代码:
为每个 创建具有不同含义或映射的不同 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
参数的原因是什么,但为了清楚起见,我会把它分解成它自己的方法。
- 如图所示,基值只能在创建新对象时赋值。这可能是也可能不是一个好主意。
SetValue(n As UInt16)
方法是另一种设置方法。
- 开启
Option Strict
; value = value Or &H1UI
等代码包含隐式转换,无法编译。
使 class 通用 (Of T)
将允许您为每个变体定义一组不同的语义:
Private Enum FooBits
Flag
[Error]
Green
'...
End Enum
Private Enum BarBits
Red = 0
Charm = 1
Quark = 3
Ziggy = 4
End Enum
如果您不知道,Flag
将用于 Bit(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
的成员与其方法一起使用。 Type 是强制执行的,并且在代码中很清楚正在使用 bit/item。尝试将 BarBits
的成员与 fooB
一起使用(使用 Option Strict)将导致编译错误。它还会阻止传递一个幻数值:
barB.SetBit(2, True)
因此,对于每个新部件或地图,您唯一需要的新代码是新的 Enum
集(和 BitSetter
实例)。
如果你想让它更简洁(例如 b = barB.Get(BarBits.Ziggy)
),你需要转义 class 中的方法名称,因为它们是关键字:
Public Sub [Set](n As T, b As Boolean)
Public Function [Get](n As T) As Boolean
我已经就此主题进行了一些研究,但并没有真正找到太多相关内容。事实上,我很确定我已经知道这个问题的答案,但我还是要问,以防万一有一些我不知道的高级技术。 (有相当高的概率)你能声明结构的名称吗?s/class 的属性或至少通过某种构造函数重命名它们?
基本上,长话短说,我正在尝试创建一个联合结构,它可以有效地为您提供位域样式标志,但使您能够在声明时为标志指定名称,以使代码看起来更简洁。我知道您在 C 语言中做同样的事情,将一个整数 (char/double/whatever) 和一个位域结构结合起来。我基本上可以做到这一点:
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;
但我想在我的代码中获得相同级别的 "cleanliness",而不必有一个巨大的声明,每次我想使用它时都必须复制并重写一半。
就像我一开始说的,我假设我偏离了基地并且没有办法做我在 VB.Net 中提出的建议,但如果有人有任何想法,我'我很想听他们说。
您不能在运行时创建或重命名属性,因为编译器需要知道它们是什么。根据评论,这是一种使用最少的新代码:
为每个 创建具有不同含义或映射的不同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
参数的原因是什么,但为了清楚起见,我会把它分解成它自己的方法。 - 如图所示,基值只能在创建新对象时赋值。这可能是也可能不是一个好主意。
SetValue(n As UInt16)
方法是另一种设置方法。 - 开启
Option Strict
;value = value Or &H1UI
等代码包含隐式转换,无法编译。
使 class 通用 (Of T)
将允许您为每个变体定义一组不同的语义:
Private Enum FooBits
Flag
[Error]
Green
'...
End Enum
Private Enum BarBits
Red = 0
Charm = 1
Quark = 3
Ziggy = 4
End Enum
如果您不知道,Flag
将用于 Bit(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
的成员与其方法一起使用。 Type 是强制执行的,并且在代码中很清楚正在使用 bit/item。尝试将 BarBits
的成员与 fooB
一起使用(使用 Option Strict)将导致编译错误。它还会阻止传递一个幻数值:
barB.SetBit(2, True)
因此,对于每个新部件或地图,您唯一需要的新代码是新的 Enum
集(和 BitSetter
实例)。
如果你想让它更简洁(例如 b = barB.Get(BarBits.Ziggy)
),你需要转义 class 中的方法名称,因为它们是关键字:
Public Sub [Set](n As T, b As Boolean)
Public Function [Get](n As T) As Boolean