有没有一种语法可以进行反向推理? [英] Is there a syntax does a reversed type inference?

查看:113
本文介绍了有没有一种语法可以进行反向推理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我试图回答这个问题时:

是否有可能摆脱Service类中的TClient泛型类型



我发现了一个奇怪的用法,我从来没有设计过这种不可编译的语法,下面是我遇到的一些问题:

  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 中是通用的。



在很多情况下类似通过一个非泛型类型的额外静态方法,通过类型推断来创建一个泛型类型的实例 - 但具体情况通常是你有两个类型参数,并且你想指定一个 >

需要注意的一点是, Action< Concrete> 仅仅是而不是一个动作< IGeneric< object>> 。例如, Concrete 可能会暴露一些 Action< Concrete> 可能依赖的额外属性 - 但给定一个 Action< IGeneric< object>> 你可以很容易地用 实现 IGeneric< object> 。您现有的 SomeMethod 尝试按照具体的动作< U> 而不是 Action< IGeneric< T>> - 但在那时使用操作相对困难。这很少(根据我的经验)一种实用的方法,即使是类型推理的作品。



只要您更改为真正的协变代理(并且假设您正在使用C#4),那么除非你关心 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);
}
}


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:

interface IGeneric<T> {
}

partial class SomeClass {
    // won't compile
    public static void SomeMethod<U>(Action<T> d) where T: IGeneric<U> {
    }
}

And even if declared as:

class Concrete: IGeneric<object> {
}

partial class SomeClass {
    public static void SomeMethod<U>(Action<IGeneric<U>> d) { // compiles
    }
}

would not make the following code compile-able:

var d=default(Action<Concrete>);
SomeClass.SomeMethod(d); // won't compile

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:

public static void SomeMethod<U>(Action<T> d) where T: IGeneric<U>

is invalid because you're trying to constrain 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.

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 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.

As soon as you change to a genuinely covariant delegate (and assuming you're using C# 4), then unless you care about 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);
    }
}

这篇关于有没有一种语法可以进行反向推理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆