-
-
Notifications
You must be signed in to change notification settings - Fork 51
Defining Immutable Objects
FlatSharp does its best to support creating immutable objects, or immutable properties within objects. Immutability is a useful programming practice in some scenarios, so FlatSharp does its best to help.
Most deserialized items in FlatSharp are immutable. The exceptions are objects deserialized using the GreedyMutable
(the default) or VectorCacheMutable
options. All other options will throw a NotMutableException
when trying to modify a deserialized object.
FlatSharp also supports defining immutable tables and structs, using a few different patterns:
If you're using C# 9, FlatSharp versions 5 and above support Init Only properties declared with the following patterns. This is the preferred way to make properties immutable in C# 9.
// FBS annotation: fs_setter:"Init"
public virtual string MyProperty { get; init; }
// FBS annotation: fs_setter:"ProtectedInit"
public virtual string MyProperty { get; protected init; }
// FBS annotation: fs_setter:"ProtectedInternalInit"
public virtual string MyProperty { get; protected internal init; }
// FBS annotation: fs_setter:"Init", fs_nonVirtual:"true"
public string MyProperty { get; init; }
// FBS annotation: fs_setter:"ProtectedInit", fs_nonVirtual:"true"
public string MyProperty { get; protected init; }
// FBS annotation: fs_setter:"ProtectedInternalInit", fs_nonVirtual:"true"
public string MyProperty { get; protected internal init; }
If using C# 8, FlatSharp supports non-public setters as well:
// FBS annotation: fs_setter:"None"
public virtual string MyProperty { get; }
// FBS annotation: fs_setter:"Protected"
public virtual string MyProperty { get; protected set; }
// FBS annotation: fs_setter:"ProtectedInternal"
public virtual string MyProperty { get; protected internal set; }
// FBS annotation: fs_setter:"Protected", fs_nonVirtual:"true"
public string MyProperty { get; protected set; }
// FBS annotation: fs_setter:"ProtectedInternal", fs_nonVirtual:"true"
public string MyProperty { get; protected internal set; }
Beginning in version 5, FlatSharp does not require types to expose default constructors. This behavior is useful if you wish to define your own constructors so that objects are never instantiated the wrong way. FlatSharp will be happy with any of the following constructors on your objects:
[FlatBufferTable]
public class MyClass
{
// FlatSharp will use this constructor if it is defined. It must be public, protected, or protected internal.
// This constructor is auto-generated when using FBS files.
protected MyClass(FlatBufferDeserializationContext context) { }
// FlatSharp will use this constructor if it is defined and there is no constructor accepting
// FlatBufferDeserializationContext items. This constructor is auto-generated when using FBS files
// and the 'fs_defaultCtor' metadata attribute is not equal to 'None'.
public MyClass() { }
}
This example shows an immutable table and immutable struct defined in a way that FlatSharp can use.
[FlatBufferTable]
public class Person
{
protected Person(FlatBufferDeserializationContext context) { }
public Person(string name, Location location)
{
this.Name = name;
this.Location = location;
}
[FlatBufferItem(0)] public virtual string? Name { get; }
[FlatBufferItem(1)] public virtual Location? Location { get; }
}
[FlatBufferStruct]
public class Location
{
protected Location(FlatBufferDeserializationContext context) { }
public Location(float x, float y, float z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
// Non-Virtual properties must specify a setter
[FlatBufferItem(0)] public float X { get; protected init; }
[FlatBufferItem(1)] public float Y { get; protected init; }
[FlatBufferItem(2)] public float Z { get; protected init; }
}