使用如下定义的方法:
public class Foo<T1>
{
public void Bar<T2>(IQux<IBaz<T1, T2>> baz) { }
}
public interface IBaz<T1, T2> { }
public struct Baz : IBaz<SomeType, AnotherType> { }
public interface IQux<out T> {}
public class Qux<T> : IQux<T> {}
在调用它时,显然不可能Bar
推断T2
为AnotherType
:
new Foo<SomeType>().Bar(new Qux<Baz>());
如果 Baz
不是结构,这将起作用。当我可以按值保留传递Baz
但是能够在这种情况下推断类型时,是否有任何解决方法?
答案 0 :(得分:3)
这不是通用类型推断问题,而是通用方差问题。 Bar
无法将T2
推断为AnotherType
,因为这无效。
new Foo<SomeType>().Bar<AnotherType>(new Qux<Baz>());
此调用无效,因为Qux<Baz>
未实现IQux<IBaz<SomeType,AnotherType>>
接口,因为Bar
方法需要。 IQux<Baz>
无法投放到IQux<IBaz<SomeType,AnotherType>>
,因为值类型不支持通用差异。
要使呼叫有效,您需要向Bar
方法添加其他通用参数:
public class Foo<T1> {
public void Bar<T2,TBaz>(IQux<TBaz> baz) where TBaz:IBaz<T1,T2> { }
}
虽然只会使此调用有效:
new Foo<SomeType>().Bar<AnotherType,Baz>(new Qux<Baz>());
这里不能进行泛型类推理。
答案 1 :(得分:1)
我同意PetSerAl's answer中的分析。这不是因为类型推断无法检测到有问题的类型,而是因为您想要推断推断的问题类型对于调用实际上是无效的。类型推断合法地无法识别要在方法的类型参数位置使用的有效类型。
就解决方法而言,在我看来,特别是因为您似乎想要利用IBaz<out T>
中的协变类型参数,使Baz
成为class
一个不错的选择。
作为struct
,类型应该是不可变的。因此,将其变为不可变的class
将保留值类型语义的许多好处(一个值得注意的例外是容易的数组初始化)。并且它将允许调用成功,即使您明确提供类型参数(如上所述和PerSetAl的答案),在您的代码示例中也不会出现这种情况。