@@ -1135,15 +1135,29 @@ Expression ParseFunctionNullPropagation()
1135
1135
1136
1136
if ( args [ 0 ] is MemberExpression memberExpression )
1137
1137
{
1138
+ bool hasDefaultParameter = args . Length == 2 ;
1139
+ Expression expressionIfFalse = hasDefaultParameter ? args [ 1 ] : Expression . Constant ( null ) ;
1140
+
1138
1141
if ( _expressionHelper . TryGenerateAndAlsoNotNullExpression ( memberExpression , out Expression generatedExpression ) )
1139
1142
{
1140
- var expressionIfTrue = memberExpression ;
1141
- var expressionIfFalse = args . Length == 2 ? args [ 1 ] : Expression . Constant ( null ) ;
1143
+ return GenerateConditional ( generatedExpression , memberExpression , expressionIfFalse , errorPos ) ;
1144
+ }
1145
+
1146
+ if ( ! hasDefaultParameter )
1147
+ {
1148
+ // If no default parameter has been supplied and the member expression is a single expression, just return it.
1149
+ return memberExpression ;
1150
+ }
1142
1151
1143
- return GenerateConditional ( generatedExpression , expressionIfTrue , expressionIfFalse , errorPos ) ;
1152
+ bool canBeNullableType = TypeHelper . IsNullableType ( memberExpression . Type ) || ! memberExpression . Type . GetTypeInfo ( ) . IsPrimitive ;
1153
+ if ( canBeNullableType )
1154
+ {
1155
+ // For nullable objects, generate 'x != null ? x : null'
1156
+ var notEqualToNull = _expressionHelper . GenerateNotEqual ( memberExpression , Expression . Constant ( null ) ) ;
1157
+ return GenerateConditional ( notEqualToNull , memberExpression , expressionIfFalse , errorPos ) ;
1144
1158
}
1145
1159
1146
- // The member expression is a single expression, just return it .
1160
+ // For non-nullable with default, just ignore default and return the single expression .
1147
1161
return memberExpression ;
1148
1162
}
1149
1163
@@ -1207,59 +1221,59 @@ Expression ParseFunctionCast()
1207
1221
return Expression . ConvertChecked ( _it , resolvedType ) ;
1208
1222
}
1209
1223
1210
- Expression GenerateConditional ( Expression test , Expression expr1 , Expression expr2 , int errorPos )
1224
+ Expression GenerateConditional ( Expression test , Expression expressionIfTrue , Expression expressionIfFalse , int errorPos )
1211
1225
{
1212
1226
if ( test . Type != typeof ( bool ) )
1213
1227
{
1214
1228
throw ParseError ( errorPos , Res . FirstExprMustBeBool ) ;
1215
1229
}
1216
1230
1217
- if ( expr1 . Type != expr2 . Type )
1231
+ if ( expressionIfTrue . Type != expressionIfFalse . Type )
1218
1232
{
1219
- // If expr1 is a null constant and expr2 is ValueType:
1220
- // - create nullable constant from expr1 with type from expr2
1221
- // - convert expr2 to nullable (unless it's already nullable)
1222
- if ( Constants . IsNull ( expr1 ) && expr2 . Type . GetTypeInfo ( ) . IsValueType )
1233
+ // If expressionIfTrue is a null constant and expressionIfFalse is ValueType:
1234
+ // - create nullable constant from expressionIfTrue with type from expressionIfFalse
1235
+ // - convert expressionIfFalse to nullable (unless it's already nullable)
1236
+ if ( Constants . IsNull ( expressionIfTrue ) && expressionIfFalse . Type . GetTypeInfo ( ) . IsValueType )
1223
1237
{
1224
- Type nullableType = TypeHelper . ToNullableType ( expr2 . Type ) ;
1225
- expr1 = Expression . Constant ( null , nullableType ) ;
1226
- if ( ! TypeHelper . IsNullableType ( expr2 . Type ) )
1238
+ Type nullableType = TypeHelper . ToNullableType ( expressionIfFalse . Type ) ;
1239
+ expressionIfTrue = Expression . Constant ( null , nullableType ) ;
1240
+ if ( ! TypeHelper . IsNullableType ( expressionIfFalse . Type ) )
1227
1241
{
1228
- expr2 = Expression . Convert ( expr2 , nullableType ) ;
1242
+ expressionIfFalse = Expression . Convert ( expressionIfFalse , nullableType ) ;
1229
1243
}
1230
1244
1231
- return Expression . Condition ( test , expr1 , expr2 ) ;
1245
+ return Expression . Condition ( test , expressionIfTrue , expressionIfFalse ) ;
1232
1246
}
1233
1247
1234
- // If expr2 is a null constant and expr1 is a ValueType:
1235
- // - create nullable constant from expr2 with type from expr1
1236
- // - convert expr1 to nullable (unless it's already nullable)
1237
- if ( Constants . IsNull ( expr2 ) && expr1 . Type . GetTypeInfo ( ) . IsValueType )
1248
+ // If expressionIfFalse is a null constant and expressionIfTrue is a ValueType:
1249
+ // - create nullable constant from expressionIfFalse with type from expressionIfTrue
1250
+ // - convert expressionIfTrue to nullable (unless it's already nullable)
1251
+ if ( Constants . IsNull ( expressionIfFalse ) && expressionIfTrue . Type . GetTypeInfo ( ) . IsValueType )
1238
1252
{
1239
- Type nullableType = TypeHelper . ToNullableType ( expr1 . Type ) ;
1240
- expr2 = Expression . Constant ( null , nullableType ) ;
1241
- if ( ! TypeHelper . IsNullableType ( expr1 . Type ) )
1253
+ Type nullableType = TypeHelper . ToNullableType ( expressionIfTrue . Type ) ;
1254
+ expressionIfFalse = Expression . Constant ( null , nullableType ) ;
1255
+ if ( ! TypeHelper . IsNullableType ( expressionIfTrue . Type ) )
1242
1256
{
1243
- expr1 = Expression . Convert ( expr1 , nullableType ) ;
1257
+ expressionIfTrue = Expression . Convert ( expressionIfTrue , nullableType ) ;
1244
1258
}
1245
1259
1246
- return Expression . Condition ( test , expr1 , expr2 ) ;
1260
+ return Expression . Condition ( test , expressionIfTrue , expressionIfFalse ) ;
1247
1261
}
1248
1262
1249
- Expression expr1As2 = ! Constants . IsNull ( expr2 ) ? _parsingConfig . ExpressionPromoter . Promote ( expr1 , expr2 . Type , true , false ) : null ;
1250
- Expression expr2As1 = ! Constants . IsNull ( expr1 ) ? _parsingConfig . ExpressionPromoter . Promote ( expr2 , expr1 . Type , true , false ) : null ;
1263
+ Expression expr1As2 = ! Constants . IsNull ( expressionIfFalse ) ? _parsingConfig . ExpressionPromoter . Promote ( expressionIfTrue , expressionIfFalse . Type , true , false ) : null ;
1264
+ Expression expr2As1 = ! Constants . IsNull ( expressionIfTrue ) ? _parsingConfig . ExpressionPromoter . Promote ( expressionIfFalse , expressionIfTrue . Type , true , false ) : null ;
1251
1265
if ( expr1As2 != null && expr2As1 == null )
1252
1266
{
1253
- expr1 = expr1As2 ;
1267
+ expressionIfTrue = expr1As2 ;
1254
1268
}
1255
1269
else if ( expr2As1 != null && expr1As2 == null )
1256
1270
{
1257
- expr2 = expr2As1 ;
1271
+ expressionIfFalse = expr2As1 ;
1258
1272
}
1259
1273
else
1260
1274
{
1261
- string type1 = ! Constants . IsNull ( expr1 ) ? expr1 . Type . Name : "null" ;
1262
- string type2 = ! Constants . IsNull ( expr2 ) ? expr2 . Type . Name : "null" ;
1275
+ string type1 = ! Constants . IsNull ( expressionIfTrue ) ? expressionIfTrue . Type . Name : "null" ;
1276
+ string type2 = ! Constants . IsNull ( expressionIfFalse ) ? expressionIfFalse . Type . Name : "null" ;
1263
1277
if ( expr1As2 != null )
1264
1278
{
1265
1279
throw ParseError ( errorPos , Res . BothTypesConvertToOther , type1 , type2 ) ;
@@ -1269,7 +1283,7 @@ Expression GenerateConditional(Expression test, Expression expr1, Expression exp
1269
1283
}
1270
1284
}
1271
1285
1272
- return Expression . Condition ( test , expr1 , expr2 ) ;
1286
+ return Expression . Condition ( test , expressionIfTrue , expressionIfFalse ) ;
1273
1287
}
1274
1288
1275
1289
// new (...) function
0 commit comments