There is an error in this code, but the error message that gets raised in response does nothing to help with debugging the problem. (Also, the error that exists arguably shouldn't be an error, but that's a whole other issue.)
Reproduction Steps
using System.Reflection.Emit;
using System.Reflection;
namespace NestedTypeError
{
internal class Program
{
static void Main(string[] args)
{
try
{
var type = BuildType();
var method = type.GetMethod("Invalid")!;
var result = method.Invoke(null, []);
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private static Type BuildType()
{
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new("MyAssembly"), AssemblyBuilderAccess.RunAndCollect);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MyAssembly");
var typeBuilder = moduleBuilder.DefineType("MyType", TypeAttributes.Public, typeof(ValueType));
var nestedTypeBuilder = typeBuilder.DefineNestedType("InnerType", TypeAttributes.NestedPrivate);
var ctor = nestedTypeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
var value = nestedTypeBuilder.DefineMethod("Value", MethodAttributes.Public, typeof(int), []);
var gen = value.GetILGenerator();
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Ret);
//nestedTypeBuilder.CreateType();
var invalid = typeBuilder.DefineMethod("Invalid", MethodAttributes.Public | MethodAttributes.Static, typeof(int), []);
var il = invalid.GetILGenerator();
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Callvirt, value);
il.Emit(OpCodes.Ret);
return typeBuilder.CreateType();
}
}
}
Expected behavior
This will error out on the call to method.Invoke. A useful error message giving some clue as to the nature of the problem that would meaningfully aid in debugging it is expected.
Actual behavior
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.TypeLoadException: Could not load type 'InnerType' from assembly 'MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
at MyType.Invalid()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
--- End of inner exception stack trace ---
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at NestedTypeError.Program.Main(String[] args) in C:\Users\mason\source\repos\Repro2\NestedTypeError\NteProgram.cs:line 14
So the type InnerType cannot be loaded. OK. Why? What's wrong with it? In some cases, TypeLoadExeption gives a meaningful error message, but in this case, and several others I've run across, it does not.
The error here is that nestedTypeBuilder.CreateType() was never called. The error message really should reflect that.
(Also, should that even be necessary for a nested type? I can see decent arguments on both sides, but to me the .NET philosophy of "the pit of success" feels like the strongest argument. When I call typeBuilder.CreateType(), I intuitively expect it to create the entire type, with all of its declared members. Having it create "everything except for the nested types" feels inconsistent.)
Description
Sub-issue of https://github.com/dotnet/runtime/issues/101298.
There is an error in this code, but the error message that gets raised in response does nothing to help with debugging the problem. (Also, the error that exists arguably shouldn't be an error, but that's a whole other issue.)
Reproduction Steps
Expected behavior
This will error out on the call to method.Invoke. A useful error message giving some clue as to the nature of the problem that would meaningfully aid in debugging it is expected.
Actual behavior
So the type
InnerType
cannot be loaded. OK. Why? What's wrong with it? In some cases,TypeLoadExeption
gives a meaningful error message, but in this case, and several others I've run across, it does not.The error here is that
nestedTypeBuilder.CreateType()
was never called. The error message really should reflect that.(Also, should that even be necessary for a nested type? I can see decent arguments on both sides, but to me the .NET philosophy of "the pit of success" feels like the strongest argument. When I call
typeBuilder.CreateType()
, I intuitively expect it to create the entire type, with all of its declared members. Having it create "everything except for the nested types" feels inconsistent.)Regression?
No response
Known Workarounds
No response
Configuration
.NET Core 8, Windows 10, x64.
Other information
No response