有没有一种语法可以进行反向推理? [英] Is there a syntax does a reversed type inference?
问题描述
当我试图回答这个问题时:
我发现了一个奇怪的用法,我从来没有设计过这种不可编译的语法,下面是我遇到的一些问题:
interface IGeneric< T> {
}
部分类SomeClass {
//不会编译
public static void SomeMethod< U>(Action< T> d)其中T:IGeneric< ; U> {
}
}
即使声明为:
class具体:IGeneric< object> {
}
partial class SomeClass {
public static void SomeMethod< U>(Action< IGeneric< U> d){//编译
}
}
会使不是使以下代码可编译:
var d = default(Action< Concrete>);
SomeClass.SomeMethod(d); //不会编译
我不知道没有涉及两种类型参数。
所以我想知道是否有这样一种反向类型推断的语法?还是解决方法?
简单的答案是否定的。这甚至不是关于类型推理的 - 它是关于类型约束的。您只能添加约束在同一个声明中引入的类型参数。所以这个:
public static void SomeMethod< U>(Action< T> d)其中T:IGeneric< U>
无效,因为您试图限制 T
在 U
方面,当它是方法声明中实际引入的 U
时。事实上, T
本身不是任何类型的参数 - 但即使 SomeClass
在 T
中是通用的。
在很多情况下类似通过一个非泛型类型的额外静态方法,通过类型推断来创建一个泛型类型的实例 - 但具体情况通常是你有两个类型参数,并且你想指定一个 > 需要注意的一点是, 只要您更改为真正的协变代理(并且假设您正在使用C#4),那么除非你关心 When I tried to answer the question: Is it possible to get rid of the TClient generic type in the Service class I found a strange usage that I've never designed something of this kind of uncompilable syntax, and following is a represent of what I encountered: And even if declared as: would not make the following code compile-able: I'm not aware a syntax that works without both type parameters involved. So I'm wondering is there a syntax does this kind of a reversed type inference? Or a workaround? The simple answer is no. This isn't even initially about type inference - it's about type constraints. You can only add constrain a type parameter which is introduced in the same declaration. So this: is invalid because you're trying to constrain In many situations similar to this you can go via an extra static method in a non-generic type, to create an instance of a generic type via type inference - but the specifics are usually that you've got two type parameters and you want to specify one of them explicitly. One important point to note is that an As soon as you change to a genuinely covariant delegate (and assuming you're using C# 4), then unless you care about
这篇关于有没有一种语法可以进行反向推理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
Action< Concrete>
仅仅是而不是一个动作< IGeneric< object>>
。例如, Concrete 可能会暴露一些
Action< Concrete>
可能依赖的额外属性 - 但给定一个 Action< IGeneric< object>>
你可以很容易地用 实现 IGeneric< object>
。您现有的 SomeMethod
尝试按照具体的动作< U>
而不是 Action< IGeneric< T>>
- 但在那时使用操作相对困难。这很少(根据我的经验)一种实用的方法,即使是类型推理的作品。
U
,你可以简单地使用不同的签名:
使用System;
interface IGeneric< T> {}
$ b $ class SomeClass
{
public static void SomeMethod< T>(Func< IGeneric< T> d){}
}
类具体:IGeneric< object> {}
class Test
{
static void Main()
{
var d = default(Func< Concrete>);
//编译罚款
SomeClass.SomeMethod(d);
}
}
interface IGeneric<T> {
}
partial class SomeClass {
// won't compile
public static void SomeMethod<U>(Action<T> d) where T: IGeneric<U> {
}
}
class Concrete: IGeneric<object> {
}
partial class SomeClass {
public static void SomeMethod<U>(Action<IGeneric<U>> d) { // compiles
}
}
var d=default(Action<Concrete>);
SomeClass.SomeMethod(d); // won't compile
public static void SomeMethod<U>(Action<T> d) where T: IGeneric<U>
T
in terms of U
, when it's U
which was actually introduced in the method declaration. Indeed, T
itself isn't a type parameter anywhere - but this would fail even if SomeClass
were generic in T
.Action<Concrete>
simply is not an Action<IGeneric<object>>
. For example, Concrete
may expose some extra property which an Action<Concrete>
could depend on - but given an Action<IGeneric<object>>
you could easily call that with a different implementation of IGeneric<object>
. Your existing SomeMethod
tries to sort of work around that by specific Action<U>
instead of Action<IGeneric<T>>
- but at that point it's relatively hard to use the action. This is rarely (in my experience) a practical approach, even when type inference works.U
you can simply use a different signature:using System;
interface IGeneric<T> {}
class SomeClass
{
public static void SomeMethod<T>(Func<IGeneric<T>> d) {}
}
class Concrete: IGeneric<object> {}
class Test
{
static void Main()
{
var d = default(Func<Concrete>);
// This compiles fine
SomeClass.SomeMethod(d);
}
}