dotnet / ClangSharp

Clang bindings for .NET written in C#
MIT License
910 stars 146 forks source link

Support generating equality operators or IEquattable<T> implementation in C# via ClangSharpPInvokeGenerator #539

Open rzikm opened 5 months ago

rzikm commented 5 months ago

Consider (perhaps large) C structures received from native code and used in .NET via generated PInvoke bindings. If the structure contains padding bytes, the default equality comparison logic for ValueTypes will fallback to an inefficient implementation using runtime reflection for each struct field, not to mention boxing due to the signature of the Equals() method accepting object arguments. We would like ClangSharpPInvokeGenerator to conditionally generate IEquattable implementations for us.

I am aware that generated code uses partial annotation and so we can add IEquattable implementation ourselves, but that leaves a possibility of it getting out of sync with the generated code if new members are ever added in the future.

tannergooding commented 5 months ago

Can you give some examples where types are being used in scenarios where equality like that is required?

It's not always valid to do element-wise comparisons and there are many C struct definitions where there is an explicitly equality method exported that you're meant to use instead.

So far this has been left off as a very niche scenario where generating it by default for all types would be likely undesirable.

rzikm commented 5 months ago

Can you give some examples where types are being used in scenarios where equality like that is required?

Inside System.Net.Quic, we need to construct MsQuicConfiguration objects, the construction is expensive and those objects are expected to be reused across connections. To do this transparently, we cache these objects and one of the keys to the cache is the QUIC_SETTINGS struct

https://github.com/dotnet/runtime/blob/dcc66a7ca25696a2326f296c3d8d3ac5a13f0524/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic_generated.cs#L1061-L2039

generating it by default for all types would be likely undesirable.

I understand that, it would be fine to make this opt-in.