PacketByte Support 라이브러리

제가 1,2,4,8,10,20,40,80 이라고 표기를 했기 때문에…
그럴수있습니다…ㅋㅋ 그래서 위에 정정했습니다
감사합니다

2개의 좋아요

[Flags] 쓰면 좋은데…
Value값을 쓰지 않을 경우 기본적으로
1234…이 아닌 1,2,4,8로 변경만 할 수 있다면야 더 좋은 코드가 될거같은데으음…


Byte 안에 Bit를 쓰는 것이기 때문에 어느정도 숙련도가 있으신분들도 사용할거라 생각이 듭니다.

그렇기 때문에
Enum을 극대화로 쓰는 방법과 아니면 기본적으로 쓰면서 사용할 수 있는 방법으로 나뉘어 사용하면어떨까하네요!

PackeBuilder에는 물론 Append에는 Enum을 극대화로 쓴 경우의 기준에서 들어가는게 좋을거같구요…!

[Flags]
public enum MACHINE : byte
{
    NONE = 0,
    POWER = 1 << 0,
    RIGHT = 1 << 1,
    TOP = 1 << 2,
    LIGHT = 1 << 3,
    TEMP = 1 << 4,
    RUN = 1 << 5,
    SOUND = 1 << 6,
    ETC = 1 << 7,
}
.
.
.

new PackeBuilder()
     .Append(MACHINE.POWER | MACHINE.TOP)
.
.
.
2개의 좋아요

코드가 늘어 나긴 하지만… enum 상수가 많을때 일일히 하드코딩으로 값을 할당하기 귀찮을때 그냥 시프트 연산해주는 확장 메서드를 이용하면…(?)


public static int GetFlagValue<T>(this T enumValue) where T : Enum
{
        var pos = Array.IndexOf(Enum.GetValues(enumValue.GetType()), enumValue);
        return 1 << pos;
}

MACHINE.TEMP.GetFlagValue<MACHINE>();  // 32

GetFlagValue<MACHINE>(); ← 매번 요거 붙여서 쓰는게 더 귀찮을려나요 ?? ㅋㅋㅋ


아 답글 달고 나서 또 보니, 그냥 제너레이터 이용할 수 있으면 특정 어트리뷰트 만들어서 Flag처리된 상수 값을 자동으로 할당 되도록 코드 생성해 주면 될것도 같군요

3개의 좋아요

오 아니에요! 좋은거같아요!
그게 귀찮으면 Enum에 값 미리 적어서 쓰라고하는게…맞는거같아서요 ㅋ_ㅋ

2개의 좋아요

이 방법도 해봤는데 뭔가 제가 잘 이해를 못했는지 …잘안되네요!

2개의 좋아요

일반적인 Enum값 다중선택 즉 비트연산을 시도하면
Resharper에서는 경고 주던데, 기존은 어떤가요?

byte로 전환 하기 전에
해당 Enum에 Flag Attribute 있는지 여부만 확인할 수만 있다면 그걸로 괜찮을 것 같아요.
없을 경우에만 @aroooong 님께서 작성해주신 GetFlagValue<T> 만 호출하면 될테니까요.

2개의 좋아요

기존이라하면 Resharper 사용하지 않는 상태를 말씀하시는거겠죠?
경고 같은 상황은 없었습니다!

[Flags]를 먹인 Enum과 아닌 것에서의 차이가 있었습니다.

public Enum Machine
{
    A,
    B,
    C
}
////
[Flags]
public Enum MachineFlags
{
    A = 0x01,
    B = 0x02,
    C = 0x04
}

Machine noneFlags = A | B;
Console.WriteLine("noneFlags = ${noneFlags}");


Machine flags = A | B;
Console.WriteLine("flags = ${flags }");

/*
noneFlags = B
flags = A | B
*/

Flags Enum을 적용하지 않은 Enum의 경우
byte 전환 전부터 이미 두개의 Enum 중 가장 큰 값만 적용되기 때문에
어떻게 할 수가 없더군요…
그래서 params Machine[]을 생각해내서 아래와 같은 형태가 나오게되었습니다

EnumHelper.Byte (MACHINE.POWER, MACHINE.TOP);
2개의 좋아요

제 경우는 열거형 정의할 때 어지간하면 Value 값을 일일이 지정하는 편입니다.
미리 잘 정의해 놓으면 편리하더라구요~ ㅎㅎ
특히 어떤 정의된 값을 다른 값들의 조합으로 재정의 할 때 주로 사용하죠~
예를 들면 이렇습니다.

[Flags]
public enum Docking : byte
{
    None        = 0b0000,
    Left        = 0b0001,
    LeftTop     = 0b0011,
    Top         = 0b0010,
    TopRight    = 0b0110,
    Right       = 0b0100,
    RightBottom = 0b1100,
    Bottom      = 0b1000,
    BottomLeft  = 0b1001,
    StratchH    = 0b0101,
    StratchV    = 0b1010,
    All         = 0b1111,
}
2개의 좋아요

네 맞아요
Enum을 극대화로! 쓰시는 케이스 말했던게 그 예제 입니다!

근데 극대화가 아닌 단순하게 사용하려는 목적이다 하는 경우를
@aroooong 님의 아이디어를 통해 개발 진행 중 입니다.

// 실제 코드
[BitSupportFlags]
public enum Docking
{
    None ,
    Left,
    Top,
    Right,
    Bottom,
}
// 제네레이터된 코드
public enum Docking
{
    None = 0x00,
    Left = 0x01,
    Top = 0x02,
    Right = 0x04,
    Bottom =0x08,
}
3개의 좋아요

멋지군요~ㅎㅎ
기대하겠습니다~!

2개의 좋아요

성공했는데…
Enum은 partial 쓸 수 없기 때문에…

// 실제 코드
[BitSupportFlags]
public enum Docking
{
    None ,
    Left,
    Top,
    Right,
    Bottom,
}
// 제네레이트된 코드
public enum DockingFlags
{
    None = 0x00,
    Left = 0x01,
    Top = 0x02,
    Right = 0x04,
    Bottom =0x08,
}

(Flags는 임시로 생성된…명칭)


Enum을 Flags화 시켰기 때문에 Flags가 붙는것도 나쁘지않을거같네요!

image

2개의 좋아요

요런느낌으로 생성되게하면 원코드와의 상관관계가 좀더 명확해질거같은데 어떤가요?

// 실제 코드
[BitSupportFlags]
enum Docking : byte
{
    Left, Top, Right, Bottom,
}
// 제네레이트된 코드
[Flags]
enum DockingFlags : byte
{
    None,
    Left   = 1 << Docking.Left,   // 0b00000001
    Top    = 1 << Docking.Top,    // 0b00000010
    Right  = 1 << Docking.Right,  // 0b00000100
    Bottom = 1 << Docking.Bottom, // 0b00001000
}
static class DockingExtensions
{
    public static DockingFlags ToFlags(this Docking d) => (DockingFlags)(1 << d);
}
3개의 좋아요

오오…
좀 그럴싸하네요…!

한번 해보고공유드릴게요!

아 그리고 저 제네레이터기능은 현재 packetsupoort라이브러리에 들어갈순없고 아마 새로운 라이브러리로 해야할거같아요 …^^

제네레이터는 닷넷스탠다드2.0에서 된다고 하다보니…

3개의 좋아요

추천해주신 방법대로
구현은 완료했습니다!

이 외에도 확장 기능 구현해보았습니다. HasAnyFlag HasNotFlag

[BitSupportFlags]
enum Docking : byte
{
    Left, Top, Right, Bottom,
}
// 제네레이트된 코드
[Flags]
enum DockingFlags : byte
{
    None,
    Left   = 1 << Docking.Left,   // 0b00000001
    Top    = 1 << Docking.Top,    // 0b00000010
    Right  = 1 << Docking.Right,  // 0b00000100
    Bottom = 1 << Docking.Bottom, // 0b00001000
}
byte abc = 0x05;
var machine = data.ToEnum<MACHINEFlags> ();

if(machine.HasAnyFlag(Docking.Left)
{
   Console.WriteLine("Docking Left은 포함되어있습니다.");
}
else if(machine.HasNotFlag(Docking.Top)
{
   Console.WriteLine("Docking Top은 포함되어있지않습니다.");
}

/* output
Docking Left은 포함되어있습니다.
Docking Top은 포함되어있지않습니다.
*/
4개의 좋아요

와웅 뚝딱 만들어버리시네요 기대가 됩니다

여태까지 만든 상황을 정리해보겠습니다!

기능

  • [삭제] EnumHelper 확장메서드 기능 제거 - 소스생성기로 전부 이관 또는 다른 방법으로…
  • [삭제] ToEumString - 불필요한 기능으로 인해서
  • [구현] …Flags Enum 자동생성, NONE 누락 시 자동 생성됨
  • [구현] ToByte<T> HasFlags HasAnyFlags HasNotFlags 4개의 확장메서드 제공

예제

[BitSupportFlags]
public enum MACHINE
{
    POWER,
    RIGHT,
    TOP,
    LIGHT,
    TEMP,
    RUN,
    SOUND,
    ETC
}

Flag 데이터를 통한 Byte 생성


var MACHINEFlags = MACHINE.POWER.ToFlags() | MACHINE.RIGHT.ToFlags(); // 또는 MACHINEFlags.POWER | MACHINEFlags.RIGHT
byte byteValue = aaa.ToByte ();

Byte를 통한 Enum 생성

byte byteValue = 0x05;
var enumData = byteValue.ToEnum<MACHINE> (); // 또는 data.ToEnum<MACHINEFlags>

…Flags의 Enum값만 HasFlags를 사용할 수 있음

byte byteValue = 0x05;
var enumData = byteValue.ToEnum<MACHINE> ();

if (enumData.HasFlags (MACHINEFlags.POWER | MACHINEFlags.TOP))
{
   Console.WriteLine("POWER, TOP" 모두 포함된 Byte 데이터입니다.)
}

…Flags의 Enum의 값은 multi로데이터 사용 가능, Flags 아닌 경우엔 단일로만 사용가능

byte byteValue = 0x05;
var enumData = byteValue.ToEnum<MACHINE> ();

if (enumData.HasAnyFlags(MACHINEFlags.POWER | MACHINEFlags.TOP))
{
   Console.WriteLine("POWER, TOP"이 포함된 Byte 데이터입니다.)   
}

if (enumData.HasAnyFlags(MACHINE.POWER))
{
    Console.WriteLine("POWER"이 포함된 Byte 데이터입니다.)      
}

…Flags의 Enum의 값은 multi로데이터 사용 가능, Flags 아닌 경우엔 단일로만 사용가능

byte byteValue = 0x05;
var enumData = byteValue.ToEnum<MACHINE> ();

if (enumData.HasNotFlags(MACHINEFlags.NONE | MACHINEFlags.LIGHT))
{
      Console.WriteLine("NONE , LIGHT"는 포함되어있지않습니다.)   
}

if (enumData.HasNotFlags(MACHINE.POWER))
{
      Console.WriteLine("POWER"는 포함되어있지않습니다.)      
}
1개의 좋아요