2016-01-05 2 views
1

Я сделал несколько оглядевшихся по этому вопросу и на самом деле не смог найти много на нем. На самом деле, я уверен, что уже знаю ответ на этот вопрос, но я собираюсь спросить на всякий случай, если есть какая-то передовая техника, о которой я не знаю. (который имеет довольно высокую вероятность). Можете ли вы объявить имена свойств структуры/класса или, по крайней мере, переименовать их через какой-либо конструктор?Можете ли вы назвать свойства через конструктор Struct/Class?

В общем, длинный рассказ. Я пытаюсь создать структуру union, которая эффективно дает вам флаги стиля битполя, но дает вам возможность указывать имена флагов в объявлении, чтобы сделать код немного более чистым. Я знаю, что вы делаете то же самое в 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; 

Но я хотел бы, чтобы получить тот же уровень «чистоты» в моем коде, и не должны иметь огромное заявление, что я придется копировать и переписывать каждый раз, когда я хочу его использовать.

Как я уже сказал в начале, я предполагаю, что я ухожу с базы, и нет возможности делать то, что я предлагаю в VB.Net, но если у кого-то есть какие-то мысли, я бы хотел услышать их.

+0

Как бы код компилируется, если он знал настоящие имена свойств до времени выполнения? Вы можете использовать псевдоиндексатор и перечисление, чтобы в одном случае бит0 сопоставлялся с Foo, а в другом он отображался в Bar. Конечно, более простой подход состоял бы в том, чтобы использовать save bool, а не en/decoding bit – Plutonix

+0

. Вы также можете использовать наследование для изменения того, что означает каждая часть, и где она сопоставляется для каждого нового использования. – Plutonix

+0

@Plutonix. Основная причина, по которой я пытаюсь сделайте это, мне придется взаимодействовать со встроенной системой и декодировать передачи данных от нее. Многие поля - это просто байты или int, но есть несколько, которые растровые и используются для определения того, какие поля присутствуют в сообщении, а какие - пропущены. Поэтому я должен читать в байте, а затем проверять флажки, чтобы увидеть, какие поля находятся в этом сообщении. – balmerjd

ответ

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 is, но я бы покончил с этим в своем собственном методе для ясности.
  • Как показано, базовое значение может быть назначено только при создании нового объекта. Это может быть или не быть хорошей идеей. Метод 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 

В случае, если вы Arent знает, Flag будет для Bit (0), Error для 1 и т. д., так что по порядку или быть явным. Второй набор дает им явные значения и вместо того, чтобы определять что-то вроде [Зарезервировано], которое не должно использоваться, оно просто пропускает это значение, поэтому будет использоваться 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 (с использованием опции 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 
Смежные вопросы