Skip to content

Use Java generic type parameters constraints #11912

Closed

Description

@jonpryor

generator doesn't "forward" and use generic type constraints in bindings. Consider this Java type:

package com.xamarin.android;

public interface InvokeRunnable<T extends Runnable> {
    void invoke (T runnable);
}

Here, T is contained to be a type that implements java.lang.Runnable.

However, the binding that generator emits is:

	[Register ("com/xamarin/android/InvokeRunnable", "", "Com.Xamarin.Android.IInvokeRunnableInvoker")]
	[global::Java.Interop.JavaTypeParameters (new string [] {"T extends java.lang.Runnable"})]
	public partial interface IInvokeRunnable : IJavaObject, IJavaPeerable {

		// Metadata.xml XPath method reference: path="/api/package[@name='com.xamarin.android']/interface[@name='InvokeRunnable']/method[@name='invoke' and count(parameter)=1 and parameter[1][@type='T']]"
		[Register ("invoke", "(Ljava/lang/Runnable;)V", "GetInvoke_Ljava_lang_Runnable_Handler:Com.Xamarin.Android.IInvokeRunnableInvoker, Xamarin.Android.McwGen-Tests")]
		void Invoke (global::Java.Lang.Object p0);

	}

The Java-side parameter, which must be a java.lang.Runnable or type implementing that interface, is bound as Java.Lang.Object.

Feature request: "forward" this constraint information, and use it in the binding, so that we instead emit:

	public partial interface IInvokeRunnable : IJavaObject, IJavaPeerable {

		[Register ("invoke", "(Ljava/lang/Runnable;)V", "GetInvoke_Ljava_lang_Runnable_Handler:Com.Xamarin.Android.IInvokeRunnableInvoker, Xamarin.Android.McwGen-Tests")]
		void Invoke (global::Java.Lang.IRunnable p0);
	}

Activity

  1. removed their assignment
    on Jun 19, 2020
  2. AmrAlSayed0 commented on Feb 6, 2021

    @AmrAlSayed0

    While trying to fix issues in a Java library I'm binding I came upon this issue. Easily fixable with Metadata attr BUT I'm curious as to why the C# interface isn't a real generic interface like

    public partial interface IInvokeRunnable <T> : IJavaObject, IJavaPeerable
    where T : global::Java.Lang.IRunnable
    {
        [Register ("invoke", "(Ljava/lang/Runnable;)V", "GetInvoke_Ljava_lang_Runnable_Handler:Com.Xamarin.Android.IInvokeRunnableInvoker, Xamarin.Android.McwGen-Tests")]
        void Invoke (T p0);
    }

    I know there is a reason I'm completely overlooking because I've seen this "issue" in classes too.

  3. jpobst commented on Feb 8, 2021

    @jpobst
    Contributor

    Unlike .NET, Java generics do not exist in compiled code or at runtime. They are simply compiler magic that the compiler removes when compiling code.

    Since we bind .jar files, the generic information is gone.

    Assuming that could be fixed, we have another issue at runtime. If Java gives us an arbitrary ArrayList object and we want to convert it to a ArrayList<T>, we don't know what T is.

    For these reasons, our bindings reflect the Java compiled API (without generics) and not the source API.

  4. AmrAlSayed0 commented on Feb 8, 2021

    @AmrAlSayed0

    But generics with constraints is fine cuz you know what T is, got it. I suspected that would be the reason.

    I really want to see this implemented (+ covariant returns) because I have seen Builder<T extends Builder<T>> classes basically become useless when all of the return types of all the methods become Java.Lang.Object when it's clearly more than that.

  5. added theissue type on Apr 29, 2025
  6. removed
    enhancementProposed change to current functionality.
    on Apr 29, 2025
  7. added
    java-interopIssues migrated from dotnet/java-interop / relates to the Java.Interop subtree
    needs-triageIssues that need to be assigned.
    Area: BindingsIssues in Java Library Binding projects.
    on Jul 1, 2026
  8. dotnet-policy-service commented on Jul 1, 2026

    @dotnet-policy-service

    We suspect this issue is stale and no longer relevant. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.

  9. dotnet-policy-service commented on Jul 15, 2026

    @dotnet-policy-service

    This issue will now be closed since it had been marked "possibly-stale" but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.

  10. locked and limited conversation to collaborators on Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: BindingsIssues in Java Library Binding projects.java-interopIssues migrated from dotnet/java-interop / relates to the Java.Interop subtreeneeds-triageIssues that need to be assigned.possibly-staleIssues that are potentially no longer relevant.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions