syntax = "proto3"; option csharp_namespace = "Contoso.Messages"; message Person { int32 id = 1; string first_name = 2; string last_name = 3; }
前面的訊息定義將三個欄位指定為名稱/值對。 與 .NET 型別上的屬性類似,每個欄位都有名稱和型別。 欄位型別可以是 Protobuf 標量值型別(如 int32),也可以是其他訊息。
Protobuf 樣式指南建議使用 underscore_separated_names 作為欄位名稱。 為 .NET 應用建立的新 Protobuf 訊息應遵循 Protobuf 樣式準則。 .NET 工具會自動生成使用 .NET 命名標準的 .NET 型別。 例如,first_name Protobuf 欄位生成 FirstName .NET 屬性。
值型別對應表
.proto 型別 | C# 型別 | 備註 |
double | double | |
float | float | |
int32 | int | 使用可變長編碼方式。編碼負數時不夠高效——如果你的欄位可能含有負數,那麼請使用sint32。 |
int64 | long | 使用可變長編碼方式。編碼負數時不夠高效——如果你的欄位可能含有負數,那麼請使用sint64。 |
uint32 | uint | |
uint64 | ulong | |
sint32 | int | 使用可變長編碼方式。有符號的整型值。編碼時比通常的int32高效。 |
sint64 | long | 使用可變長編碼方式。有符號的整型值。編碼時比通常的int64高效。 |
fixed32 | uint | |
fixed64 | ulong | |
sfixed32 | int | 總是4個位元組。 |
sfixed64 | long | 總是8個位元組。 |
bool | bool | |
string | string | |
bytes | ByteString | 可能包含任意順序的位元組資料 |
值型別始終具有預設值,並且該預設值不能設定為
null
。此項約束包括
string
和
ByteString
,他們都屬於 C# 類。
string
預設為空字串,
ByteString
預設為空位元組值。嘗試將他們設定為
null
會引發錯誤。
可為 null 的型別
C# 的 Protobuf 程式碼生成使用本地型別,如 int
表示 int32
。 因此這些值始終包括在內,不能為 null
。
對於需要顯式 null 的值(例如在 C# 程式碼中使用 int?),Protobuf 的“已知型別”包括編譯為可以為 null 的 C# 型別的包裝器。 若要使用它們,請將 wrappers.proto 匯入到 .proto 檔案中,如以下程式碼所示:
syntax = "proto3" import "google/protobuf/wrappers.proto" message Person { // ... google.protobuf.Int32Value age = 5; }
wrappers.proto 型別不會在生成的屬性中公開。 Protobuf 會自動將它們對映到 C# 訊息中相應的可為 null 的 .NET 型別。 例如,google.protobuf.Int32Value 欄位生成 int? 屬性。 引用型別屬性(如 string 和 ByteString )保持不變,但可以向它們分配 null,這不會引發錯誤。
C# 型別 | 型別包裝器 |
---|---|
bool? |
google.protobuf.BoolValue |
double? |
google.protobuf.DoubleValue |
float? |
google.protobuf.FloatValue |
int? |
google.protobuf.Int32Value |
long? |
google.protobuf.Int64Value |
uint? |
google.protobuf.UInt32Value |
ulong? |
google.protobuf.UInt64Value |
string |
google.protobuf.StringValue |
ByteString |
google.protobuf.BytesValue |
集合
列表
Protobuf 中,在欄位上使用 repeated 字首關鍵字指定列表。
message Person { // ... repeated string roles = 8; }
在生成的程式碼中,repeated
欄位由 Google.Protobuf.Collections.RepeatedField<T>
泛型型別表示。
public class Person { // ... public RepeatedField<string> Roles { get; } }
RepeatedField<T> 實現了 IList<T> 介面,因此可以應用 LINQ 查詢,或者將其轉換為陣列或列表。 RepeatedField<T> 屬性沒有公開的設定器,所以他在內部保證了不可為空。需要向其中新增資料時呼叫 Add 方法即可:
var person = new Person(); // Add one item. person.Roles.Add("user"); // Add all items from another collection. var roles = new [] { "admin", "manager" }; person.Roles.Add(roles);
字典
.NET IDictionary<TKey,TValue> 型別在 Protobuf 中使用 map 表示。
message Person { // ... map<string, string> attributes = 9; }
在生成的 .NET 程式碼中,map 欄位由 Google.Protobuf.Collections.MapField<TKey, TValue> 泛型型別表示。 MapField <TKey, TValue> 實現了 IDictionary <TKey, TValue> 介面。 與 repeated 屬性一樣,map 屬性沒有公開的設定器 。
var person = new Person(); // Add one item. person.Attributes["created_by"] = "James"; // Add all items from another collection. var attributes = new Dictionary<string, string> { ["last_modified"] = DateTime.UtcNow.ToString() }; person.Attributes.Add(attributes);