Резюме для программиста
Вот в этом куске ничего не напрягает?
Если вы про постоянный вызов 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 нужно заменить на эти два метода. Это будет лучшим решением.