• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Use in C#    {#flatbuffers_guide_use_c-sharp}
2==============
3
4## Before you get started
5
6Before diving into the FlatBuffers usage in C#, it should be noted that
7the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
8general FlatBuffers usage in all of the supported languages (including C#).
9This page is designed to cover the nuances of FlatBuffers usage,
10specific to C#.
11
12You should also have read the [Building](@ref flatbuffers_guide_building)
13documentation to build `flatc` and should be familiar with
14[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
15[Writing a schema](@ref flatbuffers_guide_writing_schema).
16
17## FlatBuffers C# code location
18
19The code for the FlatBuffers C# library can be found at
20`flatbuffers/net/FlatBuffers`. You can browse the library on the
21[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
22FlatBuffers).
23
24## Building the FlatBuffers C# library
25
26The `FlatBuffers.csproj` project contains multitargeting for .NET Standard 2.1,
27.NET Standard 2.0, and .NET Framework 4.6 (Unity 2017). Support for .NET
28Framework 3.5 (Unity 5) is provided by the `FlatBuffers.net35.csproj` project.
29In most cases (including Unity 2018 and newer), .NET Standard 2.0 is
30recommended.
31
32You can build for a specific framework target when using the cross-platform
33[.NET Core SDK](https://dotnet.microsoft.com/download) by adding the `-f`
34command line option:
35
36~~~{.sh}
37    dotnet build -f netstandard2.0 "FlatBuffers.csproj"
38~~~
39
40The `FlatBuffers.csproj` project also provides support for defining various
41conditional compilation symbols (see "Conditional compilation symbols" section
42below) using the `-p` command line option:
43
44~~~{.sh}
45    dotnet build -f netstandard2.1 -p:ENABLE_SPAN_T=true -p:UNSAFE_BYTEBUFFER=true "FlatBuffers.csproj"
46~~~
47
48## Testing the FlatBuffers C# library
49
50The code to test the libraries can be found at `flatbuffers/tests`.
51
52The test code for C# is located in the [FlatBuffers.Test](https://github.com/
53google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
54tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
55https://www.visualstudio.com), and compile/run the project.
56
57Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
58Once you have installed Mono, you can run the tests from the command line
59by running the following commands from inside the `FlatBuffers.Test` folder:
60
61~~~{.sh}
62    mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
63    mono Assert.exe
64~~~
65
66## Using the FlatBuffers C# library
67
68*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
69example of how to use FlatBuffers in C#.*
70
71FlatBuffers supports reading and writing binary FlatBuffers in C#.
72
73To use FlatBuffers in your own code, first generate C# classes from your
74schema with the `--csharp` option to `flatc`.
75Then you can include both FlatBuffers and the generated code to read
76or write a FlatBuffer.
77
78For example, here is how you would read a FlatBuffer binary file in C#:
79First, import the library and generated code. Then, you read a FlatBuffer binary
80file into a `byte[]`.  You then turn the `byte[]` into a `ByteBuffer`, which you
81pass to the `GetRootAsMyRootType` function:
82
83~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
84    using MyGame.Example;
85    using FlatBuffers;
86
87    // This snippet ignores exceptions for brevity.
88    byte[] data = File.ReadAllBytes("monsterdata_test.mon");
89
90    ByteBuffer bb = new ByteBuffer(data);
91    Monster monster = Monster.GetRootAsMonster(bb);
92~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93
94Now you can access the data from the `Monster monster`:
95
96~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
97    short hp = monster.Hp;
98    Vec3 pos = monster.Pos;
99~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100
101C# code naming follows standard C# style with PascalCasing identifiers,
102e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
103available as properties instead of parameterless accessor methods.
104The performance-enhancing methods to which you can pass an already created
105object are prefixed with `Get`, e.g.:
106
107~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
108    // property
109    var pos = monster.Pos;
110
111    // method filling a preconstructed object
112    var preconstructedPos = new Vec3();
113    monster.GetPos(preconstructedPos);
114~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115
116## Storing dictionaries in a FlatBuffer
117
118FlatBuffers doesn't support dictionaries natively, but there is support to
119emulate their behavior with vectors and binary search, which means you
120can have fast lookups directly from a FlatBuffer without having to unpack
121your data into a `Dictionary` or similar.
122
123To use it:
124-   Designate one of the fields in a table as the "key" field. You do this
125    by setting the `key` attribute on this field, e.g.
126    `name:string (key)`.
127    You may only have one key field, and it must be of string or scalar type.
128-   Write out tables of this type as usual, collect their offsets in an
129    array.
130-   Instead of calling standard generated method,
131    e.g.: `Monster.createTestarrayoftablesVector`,
132    call `CreateSortedVectorOfMonster` in C#
133    which will first sort all offsets such that the tables they refer to
134    are sorted by the key field, then serialize it.
135-   Now when you're accessing the FlatBuffer, you can use
136    the `ByKey` accessor to access elements of the vector, e.g.:
137    `monster.TestarrayoftablesByKey("Frodo")` in C#,
138    which returns an object of the corresponding table type,
139    or `null` if not found.
140    `ByKey` performs a binary search, so should have a similar
141    speed to `Dictionary`, though may be faster because of better caching.
142    `ByKey` only works if the vector has been sorted, it will
143    likely not find elements if it hasn't been sorted.
144
145## Text parsing
146
147There currently is no support for parsing text (Schema's and JSON) directly
148from C#, though you could use the C++ parser through native call
149interfaces available to each language. Please see the
150C++ documentation for more on text parsing.
151
152## Object based API
153
154FlatBuffers is all about memory efficiency, which is why its base API is written
155around using as little as possible of it. This does make the API clumsier
156(requiring pre-order construction of all data, and making mutation harder).
157
158For times when efficiency is less important a more convenient object based API
159can be used (through `--gen-object-api`) that is able to unpack & pack a
160FlatBuffer into objects and standard `System.Collections.Generic` containers,
161allowing for convenient construction, access and mutation.
162
163To use:
164
165~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
166    // Deserialize from buffer into object.
167    MonsterT monsterobj = GetMonster(flatbuffer).UnPack();
168
169    // Update object directly like a C# class instance.
170    Console.WriteLine(monsterobj.Name);
171    monsterobj.Name = "Bob";  // Change the name.
172
173    // Serialize into new flatbuffer.
174    FlatBufferBuilder fbb = new FlatBufferBuilder(1);
175    fbb.Finish(Monster.Pack(fbb, monsterobj).Value);
176~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177
178### Json Serialization
179
180An additional feature of the object API is the ability to allow you to
181serialize & deserialize a JSON text.
182To use Json Serialization, add `--cs-gen-json-serializer` option to `flatc` and
183add `Newtonsoft.Json` nuget package to csproj.
184
185~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
186    // Deserialize MonsterT from json
187    string jsonText = File.ReadAllText(@"Resources/monsterdata_test.json");
188    MonsterT mon = MonsterT.DeserializeFromJson(jsonText);
189
190    // Serialize MonsterT to json
191    string jsonText2 = mon.SerializeToJson();
192~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
193
194* Limitation
195  * `hash` attribute currentry not supported.
196* NuGet package Dependency
197  * [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
198
199## Conditional compilation symbols
200
201There are three conditional compilation symbols that have an impact on
202performance/features of the C# `ByteBuffer` implementation.
203
204* `UNSAFE_BYTEBUFFER`
205
206  This will use unsafe code to manipulate the underlying byte array. This can
207  yield a reasonable performance increase.
208
209* `BYTEBUFFER_NO_BOUNDS_CHECK`
210
211  This will disable the bounds check asserts to the byte array. This can yield a
212  small performance gain in normal code.
213
214* `ENABLE_SPAN_T`
215
216  This will enable reading and writing blocks of memory with a `Span<T>` instead
217  of just `T[]`. You can also enable writing directly to shared memory or other
218  types of memory by providing a custom implementation of `ByteBufferAllocator`.
219  `ENABLE_SPAN_T` also requires `UNSAFE_BYTEBUFFER` to be defined, or .NET
220  Standard 2.1.
221
222Using `UNSAFE_BYTEBUFFER` and `BYTEBUFFER_NO_BOUNDS_CHECK` together can yield a
223performance gain of ~15% for some operations, however doing so is potentially
224dangerous. Do so at your own risk!
225
226<br>
227