dotnet/efcore · error · NotImplementedException
Compound assignment of private property not yet supported
Error message
Compound assignment of private property not yet supported
What it means
For non-public properties the generated [UnsafeAccessor] setter handles only simple assignment. A compound assignment (+=, -=, ...) on a private property would need a read through the get accessor and a write through the set accessor as separate operations, which is not implemented, so TranslateNonPublicMemberAssignment throws NotImplementedException when assignmentKind is not SimpleAssignmentExpression.
Source
Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:1736
: memberExpression.Member,
forWrite: true);
// The unsafe accessor declaration has been created; invoke it.
Result = memberExpression.Member switch
{
FieldInfo => AssignmentExpression(
assignmentKind,
(ExpressionSyntax)_g.InvocationExpression(
_g.IdentifierName(unsafeAccessorDeclaration.Identifier.Text),
Translate<ExpressionSyntax>(memberExpression.Expression)),
Translate<ExpressionSyntax>(value)),
PropertyInfo =>
_g.InvocationExpression(
_g.IdentifierName(unsafeAccessorDeclaration.Identifier.Text), Translate<ExpressionSyntax>(memberExpression.Expression),
assignmentKind is SyntaxKind.SimpleAssignmentExpression
? Translate<ExpressionSyntax>(value)
: throw new NotImplementedException("Compound assignment of private property not yet supported")),
_ => throw new UnreachableException()
};
}
private MethodDeclarationSyntax GetUnsafeAccessorDeclaration(MemberInfo member, bool forWrite = false)
{
MethodDeclarationSyntax? unsafeAccessorDeclaration;
switch (member)
{
case FieldInfo field:
{
// Note that we generate two accessors for fields (get/set), since the get accessor needs to be used in expression trees,
// which don't support ref return
if (_fieldUnsafeAccessors.TryGetValue((field, forWrite), out unsafeAccessorDeclaration))
{
return unsafeAccessorDeclaration;View on GitHub (pinned to dbf9771522)
Solutions
- Expand the compound assignment into an explicit read plus a simple write: privateProp = privateProp + value (simple assignment, value is the sum).
- Make the property public so the normal C# compound-assignment path applies.
- Perform the accumulation outside the compiled query expression.
Example fix
// before x.Counter += n; // AddAssign on a private property -> throws // after x.Counter = x.Counter + n; // simple assignment; read and write each supported
Defensive patterns
Strategy: validation
Validate before calling
// Flag compound assignment on non-public properties
protected override Expression VisitBinary(BinaryExpression b) {
if (b.NodeType != ExpressionType.Assign && b.Left is MemberExpression m
&& m.Member is System.Reflection.PropertyInfo p
&& !(p.GetMethod?.IsPublic ?? false)) Found = true;
return b;
} Prevention
- Expand += into an explicit read plus simple write.
- Make the property public if compound assignment is needed.
- Perform accumulation outside the compiled expression.
When it happens
Trigger: A lambda performs a compound assignment on a non-public property, e.g. privateProp += value, where privateProp is a property with non-public accessors reached via the unsafe-accessor path.
Common situations: Accumulating into a private/internal property counter inside a compiled expression; using += on a property whose accessors are not public.
Related errors
- Private static field assignment
- Private static field access
- DebugInfo nodes are not supporting when translating expressi
- Null argument in VisitLabelTarget
- Non-void label target
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/c35755977cede226.
Report an issue: GitHub.