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

Inconsistent behavior using interface with generic out and derived classes with explicit implementations #103365

Closed
chschrae opened this issue Jun 12, 2024 · 5 comments
Assignees
Milestone

Comments

@chschrae
Copy link

Description

When using an interface with a generic out type, an explicit implementation, and a derived class, the base classes implementation is called instead of the derived class when running on Android. Running on Windows yields the expected behavior.

Reproduction Steps

Given an interface:

public interface IBaseInterface<out T>
{
    public void explicitDeclaration();
}

and a couple of classes:

public class BasicBaseClass : IBaseInterface<BasicBaseClass>
{
    string className = "BasicBaseClass";
    void IBaseInterface<BasicBaseClass>.explicitDeclaration()
    {
        // This is a test
        System.Diagnostics.Debug.WriteLine($"explicitDeclaration from {className}");
    }
}

public class BasicDerivedClass : BasicBaseClass, IBaseInterface<BasicDerivedClass>
{
    string className = "BasicDerivedClass";
    void IBaseInterface<BasicDerivedClass>.explicitDeclaration()
    {
        // This is a test
        System.Diagnostics.Debug.WriteLine($"explicitDeclaration from {className}");
    }
}

You can then create some objects in a list and iterate over them to call their function:

var list = new List<IBaseInterface<BasicBaseClass>>();
list.Add(new BasicBaseClass());
list.Add(new BasicDerivedClass());

foreach (var item in list)
{
    item.explicitDeclaration();
}

Expected behavior

I would expect the behavior to be the same on Android and Windows.

Actual behavior

The printouts you will see when running on Windows is:

explicitDeclaration from BasicBaseClass
explicitDeclaration from BasicDerivedClass

and when running on Android:

[0:] explicitDeclaration from BasicBaseClass
[0:] explicitDeclaration from BasicBaseClass

Regression?

No response

Known Workarounds

No response

Configuration

.NET 8
Android 33 and Windows x64

Other information

This only occurs with explicit interface declarations. If you simply hide the base implementation, the issue does not occur. This is true for implicit hiding, 'new' keyword, and overriding virtual functions.

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 12, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Jun 12, 2024
@steveisok steveisok added area-VM-meta-mono and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 12, 2024
@steveisok steveisok added this to the 9.0.0 milestone Jun 12, 2024
@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Jun 12, 2024
@kg
Copy link
Member

kg commented Jun 14, 2024

Based on local testing, it looks like both mono x86 jit and mono interpreter also do this incorrectly.

@kg
Copy link
Member

kg commented Jun 14, 2024

As an interim workaround, a construction like this appears to work:

public class BasicDerivedClass : BasicBaseClass, IBaseInterface<BasicBaseClass>, IBaseInterface<BasicDerivedClass>
{
    string className = "BasicDerivedClass";
    string IBaseInterface<BasicBaseClass>.explicitDeclaration()
    {
        return className;
    }

    string IBaseInterface<BasicDerivedClass>.explicitDeclaration()
    {
        return className;
    }
}

I'm guessing whatever your real scenario is might make it impossible to apply this as a workaround though.

kg added a commit that referenced this issue Jul 21, 2024
* Slightly reduce memory usage for classes without a variance search table (many of them)
* Make the variance search table for a given class larger, but remove the need to recursively search every table in the hierarchy
* Optimize out the additional interfaces list scan to compute the interface offset once we find a match in the variance table
@kg
Copy link
Member

kg commented Aug 5, 2024

This should be fixed now. Feel free to reopen if it's not fixed for your real scenario.

@kg kg closed this as completed Aug 5, 2024
@chschrae
Copy link
Author

chschrae commented Aug 5, 2024

Can you verify what version will have the fix?

@kg
Copy link
Member

kg commented Aug 5, 2024

Preview 7 should have it. RC1 will as well.

joseharriaga added a commit to joseharriaga/openai-in-typespec that referenced this issue Sep 3, 2024
…238)

This is the same issue that we saw previously with `ChatMessage`'s serialization in unity/mono/etc.

See: dotnet/runtime#103365

See: #138
@github-actions github-actions bot locked and limited conversation to collaborators Sep 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants