Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot compile interface with generic type parameter #277

Open
woahbust opened this issue Dec 25, 2023 · 5 comments
Open

cannot compile interface with generic type parameter #277

woahbust opened this issue Dec 25, 2023 · 5 comments
Labels
bug Something isn't working

Comments

@woahbust
Copy link

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

bug

@woahbust woahbust added the bug Something isn't working label Dec 25, 2023
@ElektroKill
Copy link
Member

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!

@ZzZombo
Copy link

ZzZombo commented May 14, 2024

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?

@ZzZombo
Copy link

ZzZombo commented May 16, 2024

@ElektroKill, could you please lend me a hand with this?

@ElektroKill
Copy link
Member

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.
dnSpy_rg5YR4e8tp

@ElektroKill
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants