Aller au contenu principal

🧬 C# vers Protobuf (proto3) — Guide pratique

Ce guide explique comment mapper efficacement les types C# vers Protobuf (proto3), avec des exemples concrets, des tableaux explicatifs et des pièges courants à éviter.


🧪 Types scalaires

Le tableau suivant présente la correspondance entre les types C#, les types Protobuf natifs et les wrappers Protobuf utilisés pour gérer la nullabilité.

Type C#Type Protobuf (proto3)Wrapper Protobuf (nullable)
intint32google.protobuf.Int32Value
longint64google.protobuf.Int64Value
uintuint32google.protobuf.UInt32Value
ulonguint64google.protobuf.UInt64Value
shortint32google.protobuf.Int32Value
ushortuint32google.protobuf.UInt32Value
byteuint32google.protobuf.UInt32Value
sbyteint32google.protobuf.Int32Value
boolboolgoogle.protobuf.BoolValue
floatfloatgoogle.protobuf.FloatValue
doubledoublegoogle.protobuf.DoubleValue
decimalstringgoogle.protobuf.StringValue
stringstringgoogle.protobuf.StringValue
byte[]bytesgoogle.protobuf.BytesValue
DateTimegoogle.protobuf.Timestampgoogle.protobuf.Timestamp
TimeSpangoogle.protobuf.Durationgoogle.protobuf.Duration
Guidstringgoogle.protobuf.StringValue

🧩 Cas particulier : decimal

Le type decimal n’existe pas nativement en Protobuf.

Solutions courantes :

ApprocheDescriptionAvantagesInconvénients
stringStockage textuelPrécision conservéeParsing requis
int64 + facteurValeur multipliée (ex: ×100)PerformantGestion manuelle
Message dédiéunits + nanosTrès précisPlus complexe

📝 Astuce : pour les montants financiers, préférez un int64 avec facteur d’échelle documenté.


🧱 Types complexes

Correspondance entre structures C# et structures Protobuf.

C#ProtobufRemarques
enumenumValeurs entières
class / recordmessageDTO / contrats
List<T>repeated TOrdre conservé
T[]repeated TÉquivalent
Dictionary<K,V>map<K,V>K limité aux scalaires
Nullable<T>Wrapper ProtobufRequis en proto3

🛠️ Exemples de définitions

📄 Classe C#

public record User(
Guid Id,
string Name,
int? Age,
DateTime CreatedAt
);

📦 Message Protobuf

syntax = "proto3";

import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";

message User {
string id = 1;
string name = 2;
google.protobuf.Int32Value age = 3;
google.protobuf.Timestamp created_at = 4;
}

ℹ️ Note : Les champs sont numérotés une seule fois et ne doivent jamais être réutilisés.


🔗 Imports nécessaires

Ces imports sont requis selon les types utilisés.

import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

🧯 Problèmes fréquents / Causes probables

ProblèmeCause probableSolution
Champ toujours à 0Type scalaire non nullableUtiliser un wrapper
Date incorrecteFuseau horaire ignoréToujours utiliser UTC
Valeur décimale tronquéeConversion decimaldoubleÉviter double
Map invalideClé non scalaireUtiliser string ou int
Champ suppriméNuméro réutiliséNe jamais réutiliser un tag