Open woahbust opened 11 months ago
Hello,
This issue occurs due to a type naming behavior of the C# compiler. When you compile interface interface ITest<T>
to IL, we get an interface type with a type name of ITest`1
and with one generic parameter defined. The number after the backtick stores information about the number of generic parameters in a type. This is necessary to allow multiple C# types with the same name to have different generic parameter counts. On the metadata (IL) level, type resolution is performed via the name so having two types with the same name would create a conflict. To circumvent this conflict this backtick and the generic parameter count is added. This interesting naming behavior is also responsible for this issue!
When we create the interface through dnSpy, call it ITest
, and add a generic parameter, we get, on the metadata level, an interface type with the name ITest
and one generic parameter defined. Notice this differs from what the C# compiler produces! Then when we go to edit the type and click compile, the C# compiler will produce a new interface type with the name ITest`1
and one generic parameter defined. When dnSpy tries to map this new type to the old type to merge the changes, it fails as no type is defined with such a name!
The simple fix is to ensure that the type names match the naming convention used by the C# compiler for types with generic parameters and add the backticks and generic parameter numbers when changing the number of generic parameters.
Something to avoid such mishaps in the future could be added too, perhaps a message box when editing a type that gives the option to automatically update the type name?
Hope this explains the issue well and provides a solution to your problem!
The simple fix is to ensure that the type names match the naming convention used by the C# compiler for types with generic parameters and add the backticks and generic parameter numbers when changing the number of generic parameters.
Sorry, as I struggle with this right now, please elaborate on what is needed to be done in order to compile changed code. EDIT: I have a class named CustomBlockValue
with a single generic parameter T
. What do you mean by ensuring type names match?
@ElektroKill, could you please lend me a hand with this?
In order for the compile functionality to work your newly added type must have a type name that matches the amount of generic parameters present. If your type (in this case a class) CustomBlockValue
has one generic parameter, you must ensure that when you right-click and select Edit Type
the name that is shown is CustomBlockValue`1
. This is necessary as dnSpy/Roslyn needs this suffix indicating generic parameter count to be present.
Notice the difference in behavior in the following demonstration when the name contains or does not contain the generic suffix.
Note: If you created a new class in dnSpy and then try to use it when editing a completely different type in C# editor it most likely will not work due to a limitation in the current implementation of the C# editor.
dnSpyEx version
6.4.1
Describe the Bug
When trying to compile an interface with a generic type parameter, an error is thrown that the edited interface could not be found.
How To Reproduce
Create an interface, then give it a generic type parameter either by editing the code or through the 'Generic Params' tab from the 'Edit Type' menu. Trying to compile the interface should now throw an error.
Expected Behavior
The interface gets compiled and has a generic type parameter.
Actual Behavior
Compiling throws an error
Additional Context