diff --git a/Il2CppDumper/Il2CppCSharpDumper.cs b/Il2CppDumper/Il2CppCSharpDumper.cs index 415a2d9..46644fb 100644 --- a/Il2CppDumper/Il2CppCSharpDumper.cs +++ b/Il2CppDumper/Il2CppCSharpDumper.cs @@ -418,8 +418,16 @@ namespace Il2CppInspector // IL2CPP doesn't seem to retain return type attributes //writer.Append(method.ReturnType.CustomAttributes.ToString(prefix + "\t", "return: ", emitPointer: !SuppressMetadata)); writer.Append($"{prefix}\t{method.GetModifierString(scope)}"); - if (method.Name != "op_Implicit" && method.Name != "op_Explicit") + + // Finalizers become destructors + if (method.Name == "Finalize" && method.IsVirtual && method.ReturnType.FullName == "System.Void" && method.IsFamily) + writer.Append("~" + method.DeclaringType.UnmangledBaseName); + + // Regular method or operator overload + else if (method.Name != "op_Implicit" && method.Name != "op_Explicit") writer.Append($"{method.ReturnParameter.GetReturnParameterString(scope)} {method.CSharpName}{method.GetTypeParametersString(scope)}"); + + // User-defined conversion operator else writer.Append($"{method.CSharpName}{method.ReturnType.GetScopedCSharpName(scope)}"); writer.Append("(" + method.GetParametersString(scope, !SuppressMetadata) + ")"); diff --git a/Il2CppInspector/Reflection/MethodBase.cs b/Il2CppInspector/Reflection/MethodBase.cs index 7a3e424..82c620a 100644 --- a/Il2CppInspector/Reflection/MethodBase.cs +++ b/Il2CppInspector/Reflection/MethodBase.cs @@ -135,6 +135,9 @@ namespace Il2CppInspector.Reflection // Static constructors can not have an access level modifier { IsConstructor: true, IsStatic: true } => "", + // Finalizers can not have an access level modifier + { Name: "Finalize", IsVirtual: true, IsFamily: true } => "", + // Explicit interface implementations do not have an access level modifier { IsVirtual: true, IsFinal: true, Attributes: var a } when (a & MethodAttributes.VtableLayoutMask) == MethodAttributes.NewSlot && Name.IndexOf('.') != -1 => "", @@ -162,7 +165,7 @@ namespace Il2CppInspector.Reflection if (IsFinal && (Attributes & MethodAttributes.VtableLayoutMask) == MethodAttributes.ReuseSlot) modifiers.Append("sealed override "); // All abstract, override and sealed methods are also virtual by nature - if (IsVirtual && !IsAbstract && !IsFinal) + if (IsVirtual && !IsAbstract && !IsFinal && Name != "Finalize") modifiers.Append((Attributes & MethodAttributes.VtableLayoutMask) == MethodAttributes.NewSlot ? "virtual " : "override "); if (IsStatic) modifiers.Append("static ");