GirCore1007
- Title: Regular C# constructors on native classes will be removed in a future version.
GirCore aims to provide a deep integration with GObject. It does not want to hide its specific semantics as this leads to possible corner cases or unexpected behavior from a user point of view. Instead, GirCore can be seen as a bridge between two different type systems (dotnet and GObject).
One of the main differences between these type systems is the way instances are created. In dotnet, constructors are used to create instances of a class. In GObject, instances are created through factory methods. There is one native factory method available on the GObject.Object class named NewWithProperties. This factory methods takes a type of any GObject and creates an instance of it. This means it is integral to the GObject type system to be able to create an instance of any class without any parameters.
To properly integrate dotnet with GObject, this means that dotnet classes which should be a subclass of GObject.Object inherit this kind of requirement from GObject. Which leads to the point to use factory methods instead of regular C# constructors.
Additionally, providing C# constructors leads to the problem that C# allows inheriting from a base class and to call the base constructor which actually breaks the integration with GObject as the newly created subclass is not known to GObject.
Let's look at how to solve the different scenarios that result from those requirements.
How to create an instance of a GObject class?
Legacy code:
//Both calls use the same constructor as `params` keyword is used.
var obj = new MyObject();
var obj = new MyObject([]);
Solution:
var obj = MyObject.NewWithProperties([]);
How to create a subclass with a parameterless constructor?
Legacy code:
public class MyObject : GObject.Object
{
private readonly GObject.Object _data;
public MyObject()
{
_data = GObject.Object.NewWithProperties([]);
...
}
}
Solution:
[GObject.Subclass<GObject.Object>]
public partial class MyObject
{
private GObject.Object _data;
[MemberNotNull(nameof(_data))]
partial void Initialize()
{
_data = GObject.Object.NewWithProperties([]);
...
}
}
How to create a subclass with parameterized constructor?
Legacy code:
public class MyObject : GObject.Object
{
private string data;
public MyObject(string data)
{
this.data = data;
...
}
}
Solution:
[GObject.Subclass<GObject.Object>]
public partial class MyObject
{
private string? data;
public static MyObject NewWithString(string data)
{
var obj = NewWithProperties([]);
obj.data = data;
return obj;
}
}
How to create a subclass of a subclass?
Solution:
[GObject.Subclass<MyObject>]
public partial class SubSubclass
{
public static SubSubclass NewWithString()
{
return NewWithProperties([]);
}
}
[GObject.Subclass<GObject.Object>]
public partial class MyObject
{
public static MyObject NewWithString()
{
return NewWithProperties([]);
}
}