Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 8, 2026

When SkipConstructor=true, the constructor was bypassed using GetUninitializedObject(), but field/property initializers were still executed. This resulted in deserialized objects receiving initializer values instead of defaults.

Changes

  • Generator: Modified GenSkipConstructor() to use default instead of member.Initializer when assigning unset fields during deserialization

Example

[ProtoContract(SkipConstructor = true)]
public partial class Message
{
    [ProtoMember(1)]
    public string Name { get; set; } = "InitializerValue";
    
    [ProtoMember(2)]
    public int Count { get; set; } = 42;
    
    public Message()
    {
        Name = "ConstructorValue";
        Count = 99;
    }
}

// Before: Deserialized empty message had Name="InitializerValue", Count=42
// After:  Deserialized empty message has Name=null, Count=0

Deserialized objects now receive true default values (null/0) for unset fields, consistent with the intent of bypassing all initialization logic.

Original prompt

This section details on the original issue you should resolve

<issue_title>Ignore field/property initializer when SkipContructor=true</issue_title>
<issue_description></issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: dameng324 <4465571+dameng324@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix issue with field initializer when SkipConstructor is true Fix: Ignore field/property initializers when SkipConstructor=true Jan 8, 2026
Copilot AI requested a review from dameng324 January 8, 2026 11:38
@codecov
Copy link

codecov bot commented Jan 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.39%. Comparing base (76f50dd) to head (a704ee7).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #146   +/-   ##
=======================================
  Coverage   98.39%   98.39%           
=======================================
  Files          99       99           
  Lines        2186     2186           
  Branches      231      231           
=======================================
  Hits         2151     2151           
  Misses         23       23           
  Partials       12       12           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

This comment has been minimized.

@dameng324 dameng324 marked this pull request as ready for review January 8, 2026 12:11
Copilot AI review requested due to automatic review settings January 8, 2026 12:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where objects deserialized with SkipConstructor=true were incorrectly receiving field/property initializer values instead of default values. When SkipConstructor=true, the intent is to bypass all initialization logic, including both constructor execution and field/property initializers.

  • Modified the code generator to only assign parsed values when they exist, allowing unset fields to remain at their default values
  • Added comprehensive test coverage to verify the fix handles properties with initializers correctly

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/LightProto.Generator/LightProtoGenerator.cs Changed GenSkipConstructor() to use conditional assignment instead of ternary operator with member.Initializer, ensuring unset fields get default values
tests/LightProto.Tests/Parsers/SkipConstructorWithInitializerTests.cs Added new test class to verify that deserialized objects with SkipConstructor=true receive default values for unset proto members, not initializer values

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@dameng324 dameng324 merged commit b1b2b37 into main Jan 8, 2026
4 of 5 checks passed
@dameng324 dameng324 deleted the copilot/ignore-field-initializer-skipconstructor branch January 8, 2026 12:15
@github-actions

This comment has been minimized.

@github-actions
Copy link

github-actions bot commented Jan 8, 2026


BenchmarkDotNet v0.15.3, Linux Ubuntu 24.04.3 LTS (Noble Numbat)
AMD EPYC 7763 2.70GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.101
  [Host]    : .NET 8.0.22 (8.0.22, 8.0.2225.52707), X64 RyuJIT x86-64-v3
  .NET 10.0 : .NET 10.0.1 (10.0.1, 10.0.125.57005), X64 RyuJIT x86-64-v3
  .NET 8.0  : .NET 8.0.22 (8.0.22, 8.0.2225.52707), X64 RyuJIT x86-64-v3
  .NET 9.0  : .NET 9.0.11 (9.0.11, 9.0.1125.51716), X64 RyuJIT x86-64-v3


Method Job Runtime Mean Error StdDev Ratio Allocated Alloc Ratio
Deserialize_ProtoBuf_net .NET 10.0 .NET 10.0 761.1 μs 1.56 μs 1.38 μs 1.24 562 KB 0.88
Deserialize_GoogleProtoBuf .NET 10.0 .NET 10.0 614.7 μs 2.49 μs 2.20 μs 1.00 648.7 KB 1.01
Deserialize_LightProto .NET 10.0 .NET 10.0 612.6 μs 1.96 μs 1.83 μs 1.00 639.98 KB 1.00
Deserialize_ProtoBuf_net .NET 8.0 .NET 8.0 888.0 μs 1.37 μs 1.21 μs 1.48 562 KB 0.88
Deserialize_GoogleProtoBuf .NET 8.0 .NET 8.0 812.0 μs 1.76 μs 1.65 μs 1.35 648.7 KB 1.01
Deserialize_LightProto .NET 8.0 .NET 8.0 601.0 μs 3.08 μs 2.73 μs 1.00 639.98 KB 1.00
Deserialize_ProtoBuf_net .NET 9.0 .NET 9.0 805.3 μs 1.66 μs 1.39 μs 1.31 562 KB 0.88
Deserialize_GoogleProtoBuf .NET 9.0 .NET 9.0 682.5 μs 1.86 μs 1.65 μs 1.11 648.7 KB 1.01
Deserialize_LightProto .NET 9.0 .NET 9.0 614.4 μs 2.93 μs 2.45 μs 1.00 639.98 KB 1.00

BenchmarkDotNet v0.15.3, Linux Ubuntu 24.04.3 LTS (Noble Numbat)
AMD EPYC 7763 2.70GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.101
  [Host]    : .NET 8.0.22 (8.0.22, 8.0.2225.52707), X64 RyuJIT x86-64-v3
  .NET 10.0 : .NET 10.0.1 (10.0.1, 10.0.125.57005), X64 RyuJIT x86-64-v3
  .NET 8.0  : .NET 8.0.22 (8.0.22, 8.0.2225.52707), X64 RyuJIT x86-64-v3
  .NET 9.0  : .NET 9.0.11 (9.0.11, 9.0.1125.51716), X64 RyuJIT x86-64-v3


Method Job Runtime Mean Error StdDev Ratio Allocated Alloc Ratio
Serialize_ProtoBuf_net .NET 10.0 .NET 10.0 923.4 μs 1.50 μs 1.33 μs 1.35 526.41 KB 1.03
Serialize_GoogleProtoBuf .NET 10.0 .NET 10.0 778.7 μs 1.59 μs 1.41 μs 1.14 512.95 KB 1.00
Serialize_LightProto .NET 10.0 .NET 10.0 684.9 μs 1.19 μs 1.05 μs 1.00 512.95 KB 1.00
Serialize_ProtoBuf_net .NET 8.0 .NET 8.0 1,063.1 μs 2.23 μs 2.08 μs 1.40 526.4 KB 1.03
Serialize_GoogleProtoBuf .NET 8.0 .NET 8.0 821.7 μs 2.01 μs 1.88 μs 1.09 512.95 KB 1.00
Serialize_LightProto .NET 8.0 .NET 8.0 757.3 μs 5.52 μs 4.89 μs 1.00 512.95 KB 1.00
Serialize_ProtoBuf_net .NET 9.0 .NET 9.0 973.2 μs 2.44 μs 2.16 μs 1.31 526.41 KB 1.03
Serialize_GoogleProtoBuf .NET 9.0 .NET 9.0 813.8 μs 1.20 μs 1.00 μs 1.09 512.95 KB 1.00
Serialize_LightProto .NET 9.0 .NET 9.0 745.7 μs 1.77 μs 1.65 μs 1.00 512.95 KB 1.00

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ignore field/property initializer when SkipContructor=true

2 participants