问题标签 [nested-generics]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
1493 浏览

java - 参数化类型参数?

我正在尝试使用一个容器创建库,该容器根据传递的描述符释放其包含的对象的实例。我想让描述符确定返回对象的类型,但描述符可以指定有界类型。我该如何实施?例如,我能得到的最接近的是:

上面的代码可以编译,但问题是ChannelArchive'sgetItem也可以返回SeekableByteChannels。这个库的用户在编译时就知道这一点(因为他们知道描述符的类型参数),所以我试图避免添加一个类型的方法参数Class来强制用户在必要时显式地转换返回的值SeekableByteChannel。我不知道如何在不强制用户强制转换的情况下getItem返回特定的子类型。ByteChannel我想做这个:

可以为每个方法添加一个Class<? extends I>参数,但是该方法的代码将完全忽略Class方法参数!它的唯一目的是帮助编译器推断类型。我认为它只是混淆了代码,以至于让用户使用instanceof检查和强制转换会更容易。

我试过这个:

但这不起作用: ChannelArchive is not abstract and does not override abstract method getItem(ChannelItemDescriptor<? extends ByteChannel>) in ArchiveContainer。我认为这是因为第二个类型参数<II extends ByteChannel>的类型擦除与<? extends ByteChannel>?

我也试过这个,它编译:

即使它可以编译,它也不会真正起作用,因为我需要ChannelItemDescriptor在该方法内部,并且生成的强制转换会破坏使用泛型的附加类型安全的目的。

我不明白为什么我不能这样做,因为在编译时就知道正确的类型。我在该ArchiveContainer接口上真正需要的是参数化类型参数,例如:<II extends I, DD extends D<II>>. 我究竟做错了什么?

注意:我实际上并没有使用ByteChanneland SeekableByteChannel,但我使用的是非常相似的。


这就是 ruakh,我确定了第 4 块中的代码。在我的情况下,用户极不可能在对ItemDescriptora 的调用中发送错误的子类getItem,尤其是因为描述符都是ArchiveContainer通过自身返回的getDescriptors

0 投票
2 回答
18297 浏览

c# - 展平 IEnumerable>; 理解泛型

我写了这个扩展方法(编译):

下面的代码导致编译时错误(找不到合适的方法),为什么?

如果我实现如下扩展,则不会出现编译时错误:

编辑(2):这个问题我认为已经回答,但它提出了另一个关于重载解决和类型约束的问题。我在这里提出的这个问题:为什么类型约束不是方法签名的一部分?

0 投票
2 回答
1295 浏览

c# - 为什么类型约束不是方法签名的一部分?

更新:从 C# 7.3 开始,这应该不再是问题。从发行说明:

当方法组包含一些类型参数不满足其约束的泛型方法时,这些成员将从候选集中删除。

C# 7.3 之前的版本:

所以我读了Eric Lippert 的 'Constraints are not part of the signature',现在我明白规范指定在重载决议之后检查类型约束,但我仍然不清楚为什么必须如此。下面是埃里克的例子:

这不会编译,因为重载解析:Foo(new Giraffe())推断这Foo<Giraffe>是最佳重载匹配,但类型约束失败并引发编译时错误。用埃里克的话来说:

这里的原则是重载解析(和方法类型推断)在参数列表和每个候选方法的形式参数列表之间找到最佳匹配。也就是说,他们查看候选方法的签名。

类型约束不是签名的一部分,但为什么不能呢?在哪些情况下考虑将类型约束作为签名的一部分是一个坏主意?实施起来很难还是不可能?我并不是在主张,如果由于某种原因无法调用最佳选择的重载,那么就默默地回退到次优;我会讨厌那个。我只是想了解为什么不能使用类型约束来影响最佳重载的选择。

我在 C# 编译器内部想象,仅用于重载解析目的(它不会永久重写方法),如下:

转换为:

为什么不能将类型约束“拉入”到形式参数列表中?这如何以任何不好的方式改变签名?我觉得它只会加强签名。然后Foo<Reptile>永远不会被视为过载候选者。

编辑2:难怪我的问题如此混乱。我没有正确阅读 Eric 的博客,并且引用了错误的示例。我在我认为更合适的示例中进行了编辑。我还将标题更改为更具体。这个问题似乎不像我最初想象的那么简单,也许我错过了一些重要的概念。我不太确定这是 stackoverflow 材料,最好将此问题/讨论移到其他地方。

0 投票
3 回答
484 浏览

java - 避免 Java 中嵌套 Map 的未经检查的强制转换

我有一个反序列化这个 JSON 的 Java 数据结构:

在 Java 中,这变成:

当然,层数是任意的,所以我不能真正在变量声明中嵌套集合。我正在做的是:

这显然 a) 使用了一些未经检查的强制转换,并且 b) 是丑陋的。我试图定义新类型来解决这个问题:

但是,这给了我一个运行时异常:

我怎样才能以干净、无警告的方式做到这一点?

0 投票
1 回答
244 浏览

c# - 迷失在仿制药和反射酱中

我正在尝试构建一个 MVC 助手,用于使用我自己的参数构建一个 MultiSelectList。我基于我不久前构建的 SelectFor 助手。SelectFor 看起来像这样:

MultiSelectFor 只是略有不同,只有一个意义不同:forExpression将是IEnumerable的属性类型的泛型idExpression。此集合将用于“预选”列表项,并将作为表单上选定项的返回值。我(我认为)在这方面走得更远,但仍然很迷茫。

帮助表示赞赏。

更新 感谢您的回答!泛型有时会让我感到困惑。完整的解决方案如下:

再次感谢您的帮助!

0 投票
3 回答
2976 浏览

c# - 实现嵌套的通用接口

我有以下类/接口:

我尝试使用以下代码创建一个新实例:

我收到以下错误:

有人可以解释为什么这是不可能的吗?

0 投票
2 回答
176 浏览

java - 构造函数参数在传递给超级构造函数时丢失

在我的 GWT 应用程序中,我有一个扩展超类的数据类型(用于构建和跟踪类似对象的层次结构),而超类又扩展了另一个抽象超类。在抽象类中声明了一个泛型参数,然后每个子类将其指定为自身的类型。结构如下:

当我将父参数传递给 SpecialFoo 的构造函数时,Foo 的构造函数将被称为超级构造函数,而该构造函数又会调用 AbstractFoo 的构造函数作为超级构造函数。

我遇到的问题是,当从 Foo 传递到 AbstractFoo 时,父参数被重置为 NULL。我不知道为什么会这样。谁能告诉我我需要做什么才能将它传递给抽象基类而不受伤害?


编辑: 我想我已经解决了......诀窍似乎是我必须在每个子类中声明父参数,以便对它有更具体的引用,如下所示:

0 投票
2 回答
794 浏览

c# - 嵌套通用语法歧义>>

显然,C# 和C++一样容易受到“>>”词法分析器困境的影响。

这段 C# 代码非常有效,它编译并运行得很好:

您必须为上面的 Dummy 类重载 '<' 和 '>>' 运算符。

但是编译器设法猜测在“x”情况下的含义是使用 List、Nullable 和 Guid 局部变量。在“y”的情况下,它突然决定将它们视为知名类型的名称。

这是另一个示例的更详细描述:http: //mihailik.blogspot.co.uk/2012/05/nested-generics-c-can-be-stinky.html

问题是:C# 编译器如何将 'a<b<c>>' 解析为算术表达式或泛型类型/方法?

在成功之前,它肯定不会尝试对程序的文本进行多次“遍历”,或者是吗?这将需要无限的前瞻,而且也非常复杂。

0 投票
1 回答
471 浏览

java - 如何获取泛型定义实体的 .class?

那么如何在 Java 中执行以下操作?

该问题特别发生在 List.class 中,返回的错误是:

0 投票
1 回答
1337 浏览

c# - 使用嵌套类型 arg 动态实例化对象时引发 TypeLoadException

在为OSS 项目做贡献的同时,我遇到了 TypeLoadException。我正在创建一个接缝,开发人员可以通过该接缝注入他们自己的 Repository 类来删除对 EF 的具体依赖,这样我就可以隔离我的新代码并运行一些测试。

似乎Activator.CreateInstance()针对具有嵌套类型 arg 的类型运行会在运行时创建它时遇到麻烦。我以前多次使用过这种模式,但这次不同的是我使用它来动态注入一个通用的存储库模式实现。问题似乎确实与该类型 arg 有关。我目前很难过,所以任何帮助将不胜感激。

这是我得到的错误:

以下是来自 Rock.Data 命名空间的一些相关(带注释的)代码片段:

IRepository.cs

EFRepository.cs

服务.cs

RepositoryFactory.cs

这是我在单独的 Rock.Tests 项目中使用的一些假对象和测试代码片段......

FakeRepository.cs

PageTests.cs

应用程序配置

希望这涵盖了它相当彻底。提前致谢!