Резюме для программиста
Вот в этом куске ничего не напрягает?
Если вы про постоянный вызов Reverse, то нет. Как я понял, вы хотите сделать что-то типа расширения BitConverter.GetReversedBytes, верно? Тогда не вижу в этом смысла. Во-первых, по-хорошему надо все методы класса BitConverter переписать на возможность возврата реверсивного порядка байт. Или по крайней мере те методы, что работают с более, чем однобайтовыми значениями (однобайтовые не реверсируются) - это около 20 методов. Во-вторых, это будет однострочное "расширение", с простым вызовом теж же самых методов BitConverter.GetBytes, только к каждому ещё добавится Reverse.
Можно сделать проще - сделать реверс и вызов BitConverter.GetBytes в отдельном методе для длинн данных больше одного байта. Но тогда придётся передавать параметром тип данных (или определять его в самом этом методе), и внутри метода городить развесистый свитч по типам данных, где будет вызываться конкретная перегрузка метода BitConverter.GetBytes - для соответствующего типа данных. По-моему, это лишние тормоза - беготня по веткам свича (код-то должен в реальном времени парсить поток данных, а вызываться будет много раз при каждой сериализации или десериализации пакета данных). У меня эти методы Serialize и Deserialize используются для структур данных, которые я передаю по сети. Кроме того, я постоянно вызываю Reverse в методе Deserialize, который выглядит примерно так (здесь разве что названия некоторых свойств класса длинные)
public static SetMode_SAEJ1939 Deserialize(byte[] structBytes)
{
byte[] modeBytes =
structBytes
.Take(ModeByteLength)
.Reverse()
.ToArray();
// Длина payloadBytes в байтах.
int payloadByteLength =
structBytes.Length
- ModeByteLength
- PayloadLengthBytes_byteLength
- ExtendByteLength
- IdentifierByteLength;
// Байты непосредственно данных.
byte[] payloadBytes =
structBytes
.Skip(IdentifierByteLength + PayloadLengthBytes_byteLength) // пропускаем identifierBytes и payloadLengthBytes
.Take(payloadByteLength)
.ToArray();
byte[] extendBytes =
structBytes
.Skip(ModeByteLength + PayloadLengthBytes_byteLength + payloadByteLength)
.Take(ExtendByteLength)
.Reverse()
.ToArray();
byte[] identifierBytes =
structBytes
.Skip(structBytes.Length - IdentifierByteLength)
.Take(IdentifierByteLength)
.Reverse()
.ToArray();
SetMode_SAEJ1939 structure = new SetMode_SAEJ1939()
{
_mode = (Modes)BitConverter.ToUInt32(modeBytes, 0),
_payload = payloadBytes,
_extend = BitConverter.ToBoolean(extendBytes, 0),
_identifier = BitConverter.ToUInt32(identifierBytes, 0)
};
return structure;
}
Тут бы вы какую оптимизацию предложили? По мне, если где-то в сериализации выносить что-то с постоянным вызовом реверса в отдельный метод, то и в десериализации это надо делать. Но я не вижу смысла, как уже писал - в показанном коде всё понятно, как данные обрабатываются - не надо прыгать по функциям и смотреть, что они там делают. А если делать всякие "оптимизирующие повторное использование кода" расширения, то придётся постоянно в них смотреть, что отвлекает от самого алгоритма обработки данных. Не нужно везде лепить оптимизацию повторного использование кода. В каких-то местах, как вот это, например, тупое копирование делает код более читаемым и понятным, чем прыжки по всяким хелперам и расширяющим методам. Я считаю, что вообще офигенно написано и красиво - идёт цепочка вызовов коротких названий методов IEnumerable, не прерываемая нигде всякими сторонними хелперами с длиннющими названиями - всё читаемо и удобно.
Вообще, всё это вышеперечисленное туфта. Я раньше не знал про методы IPAddress.HostToNetworkOrder Method (System.Net) | Microsoft Docs. Надо сделать как я раньше сказал - договориться, что слать в сеть сообщения с порядком байт сети - как все нормальные люди делают. Затем все значения больше одного байта - а обычно это 2-, 3- и 4-байтовые значения - передавать через вышеупомянутый метод, а получать - через его аналог IPAddress.NetworkToHostOrder Method (System.Net) | Microsoft Docs. Т.е. все Reverse нужно заменить на эти два метода. Это будет лучшим решением.