【问题标题】:Generic constraints using Xamarin使用 Xamarin 的通用约束
【发布时间】:2015-08-25 02:45:17
【问题描述】:

我有以下具有泛型类型约束的泛型类型。

public class GenericType<T> where T: IFoo
{
}

然后我尝试从开放的泛型类型创建一个封闭的泛型类型。

var fooGenericType = typeof(GenericType<>).MakeGenericType (typeof(IFoo));  
var intGenericType = typeof(GenericType<>).MakeGenericType (typeof(int)); 

在模拟器中运行时,尝试使用 int 作为预期的类型参数创建封闭的泛型类型失败。

但是,当在实际设备 (iPhone) 上运行时,它还将使用 int 创建一个封闭的泛型类型。 似乎它不尊重通用约束,但这仅发生在设备上。在模拟器上一切正常。

有什么想法吗?

【问题讨论】:

    标签: ios generics xamarin


    【解决方案1】:

    这似乎与 MonoTouch 使用 AoT 编译有关。正如here 所指出的那样,它会导致一些泛型类型的限制@

    【讨论】:

    • 我知道有关泛型及其局限性的文档。然而,这似乎不是一个限制,因为它在设备上的行为比在模拟器中运行时更宽容。非常了不起的是,可以基于泛型类型的限制创建任何封闭的泛型类型。这里有什么回退机制吗,比如 Java 中的类型擦除?
    • 不是模拟器更宽容。模拟器未运行full AOT,而设备运行。
    • 我了解到该设备正在运行完整的 AOT。恕我直言,我认为您可能误解了我的问题。只是为了澄清这在模拟器上“有效”,因为 id 由于通用约束确实引发了异常。 var intGenericType = typeof(GenericType).MakeGenericType (typeof(int));如果我在实际设备上运行完全相同的代码,它将错误地使用 int 类型参数创建一个封闭的泛型类型,而完全忽略约束。
    • 它确实忽略了约束,因为 iPhone 在运行时无法检查它。模拟器会抛出异常,因为 CLR 正在运行时检查类型约束。这就是 JIT 发挥它的魔力。它不能在 AOT 编译中发生。因此,为什么这是一个限制。
    • 这对我来说已经足够了,威廉。感谢您的澄清。尽管使用 MakeGenericType 的任何东西都可以在 iOS 上运行,但我有点惊讶,因为在编译时这些类型是未知的。你知道这在电话内部是如何工作的吗?这些类型是否由 system.object 或类似的东西支持?
    【解决方案2】:

    就像 William Barbosa 提到的,iOS 上的泛型类型存在一些限制。 当链接器认为没有必要时,会排除带有多个参数的泛型类型的组合。由于模拟器是不同的构建目标,因此链接器的工作方式可能不同。

    您可以通过在代码中的任何位置使用它们来强制链接器包含具有特定类型参数的泛型类型。 一种常见的方法是提供一个LinkerPleaseInclude.cs 文件,如下所示:https://github.com/MvvmCross/MvvmCross-Tutorials/blob/master/DailyDilbert/DailyDilbert.Touch/LinkerPleaseInclude.cs

    这里也指出:MakeGenericMethod/MakeGenericType on Xamarin.iOS

    【讨论】:

    • 问题不在于为什么它不起作用,而是为什么它起作用。我在设备上的链接器选项设置为“仅 SDK 程序集”,仍然可以创建在编译时未知的封闭泛型类型。这个怎么可能?更重要的是,为什么它允许创建不符合泛型约束的无效封闭泛型类型?我的怀疑是 xamarin“编译器”尽最大努力隐藏这些错误(可能将这些未知类型视为对象),在这种情况下,它有点错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 2016-01-09
    相关资源
    最近更新 更多