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

[ObjCRuntime] Change Runtime.GetNSObject<T> to create a new instance if the existing one is of the wrong type. Fixes #13704. #16491

Merged
merged 1 commit into from
Oct 28, 2022

Commits on Oct 27, 2022

  1. [ObjCRuntime] Change Runtime.GetNSObject<T> to create a new instance …

    …if the existing one is of the wrong type. Fixes xamarin#13704.
    
    Objective-C has an optimization where creating an empty dictionary would
    return the same instance every time (probably to a constant empty dictionary).
    
    This causes a problem with how we've bound generic dictionaries, because all
    empty dictionaries would have the same native handle, even if we'd bound them
    with different managed types.
    
    This surfaces in unfortunate ways when we try to look up a managed instance
    given a native handle, we find that we already have a managed instance, but
    the managed instance is of the wrong type.
    
    Example code:
    
        var a = new NSDictionary ();
        var b = new NSDictionary<NSString, NSString> ();
        var c = new NSDictionary<NSString, NSObject> ();
        Console.WriteLine ($"a: 0x{a.Handle:X}");
        Console.WriteLine ($"b: 0x{b.Handle:X}");
        Console.WriteLine ($"c: 0x{c.Handle:X}");
    
    would produce something like:
    
        a: 0x0x7fff80821080
        b: 0x0x7fff80821080
        c: 0x0x7fff80821080
    
    now for this code:
    
        Runtime.GetNSObject<NSDictionary<NSString, NSString>> (b.Handle)
    
    it would throw an exception like this:
    
        Unable to cast object of type 'Foundation.NSDictionary`2[[Foundation.NSString],[Foundation.NSObject]]' to type 'Foundation.NSDictionary`2[[Foundation.NSString],[Foundation.NSString]]'
    
    because we'll have the 'c' object (with type `NSDictionary<NSString, Object>`)
    in our dictionary of native handles -> managed instances, and that's not
    compatible with the desired return type from GetNSObject
    (`NSDictionary<NSString, NSString>`)
    
    This likely happens with all the non-mutable collection types we have a
    generic version of (NSArray, NSDictionary, NSOrderedSet, NSSet).
    
    Fixes xamarin#16378.
    Fixes xamarin#13704.
    rolfbjarne committed Oct 27, 2022
    Configuration menu
    Copy the full SHA
    39144a7 View commit details
    Browse the repository at this point in the history