private static void ConvertUnboxStruct(AstExpression node, XTypeReference resultType, XTypeSystem typeSystem) { // Structs must never be null. We have to handle structs here, since a newobj // might need generic arguments. These would be difficult to provide at "UnboxFromGeneric", // but will be automatically filled in by the GenericInstanceConverter // convert to (temp$ = (T)x) != null ? temp$ : default(T) // replace any unbox, but keep if otherwise. var clone = node.Code == AstCode.Unbox ? new AstExpression(node.Arguments[0]) : new AstExpression(node); // make sure we don't evaluate the expression twice. var tempVar = new AstGeneratedVariable("temp$", "") { Type = typeSystem.Object }; // T(x) var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, resultType, clone) .SetType(resultType); // temporary storage var storeTempVar = new AstExpression(node.SourceLocation, AstCode.Stloc, tempVar, txExpr) { ExpectedType = resultType }; var loadTempVar = new AstExpression(node.SourceLocation, AstCode.Ldloc, tempVar) .SetType(resultType); // default (T) var defaultT = new AstExpression(node.SourceLocation, AstCode.DefaultValue, resultType).SetType(resultType); var constructor = StructCallConverter.GetDefaultValueCtor(resultType.Resolve()); StructCallConverter.ConvertDefaultValue(defaultT, constructor); // Combine var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, resultType, storeTempVar, loadTempVar, defaultT) .SetType(resultType); node.CopyFrom(conditional); }