无法传递符合泛型约束的类型的变量

时间:2012-12-29 14:11:39

标签: c# generics interface generic-constraints

public interface ILovable<T> where T : IEquatable<T>
{
    T Care(T t);
}

public class Me : ILovable<int>
{
    public int Care(int i)
    {
        return i;
    }
}

说我有上述内容。现在下面的功能失败了:

private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>
{
    var z = me.Care(1); //cannot convert from 'int' to 'T'
}

上面的代码失败了什么? ILovable<T>有一个Care函数,其中TIEquatable<T>Care。在上面的函数中,我调用相同的T函数并传递int类型的intIEquatable<int>毕竟是{{1}}。

我做错了什么?有没有解决方法?

5 个答案:

答案 0 :(得分:3)

您的方法签名未指定ILovable<int>,它指定ILovable<T>。例如,这可以起作用:

private static void Colour(ILovable<int> me)
{
    var z = me.Care(1); //cannot convert from 'int' to 'T'
}

问题是编译器不知道你的例子中T是'int';它可以是满足约束的任何类型。这是另一种方法:

private static void Colour<T>(ILovable<T> me, T valueToCareAbout) where T : IEquatable<T>
{
    var z = me.Care(valueToCareAbout);
}
//use like this
Colour(me, 1);

答案 1 :(得分:1)

我得到的错误是:

Argument type 'int' is not assignable to parameter type 'T'

我很确定这是因为您将me定义为ILovable<T>。因此,它不会自动解析为Me类型,其中int定义为T

这样可以解决错误,因为MeT定义为int

private static void Colour<T>(Me me) where T : IEquatable<T>
        {
            var z = me.Care(1); 
        }

答案 2 :(得分:1)

那是因为方法Color说会有类型ILovable&lt;的参数。 T>而T稍后会被解析,所以在编译时我要告诉方法T是int类型。

因此,要么将ILovable作为参数传递,要么让被告传递T是int

void Colour<T>(ILovable<int> me)

或直接传递给我

void Colour<T>(Me me)

因为否则me.Care期望类型T不是int特定的

答案 3 :(得分:1)

更改以下

private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>

private static void Colour<Int32>(ILovable<int> me) 

以上将起作用。


现在是神秘部分

您在以下

中收到错误消息
private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>

因为Care期待T,而您正在提供int 它与

相同

Care((T)1)

 T t = (T)1; //This is the cause of error as int cannot be changed to T. Remember Int32 is sealed so T cannot derive from int

 Care(t); // This is fine

要完成上述工作,T必须int。要做到这一点,Colur方法语法应该像

   private static void Colour<Int32>(ILovable<int> me) 

如果您想将字符串传递给CareT应为string

  private static void Colour<string>(ILovable<string> me) 
  {
     me.Care("Hello");
  }

现在,如果我们必须修复T,那么问题就出现了为什么在Colour定义中根本需要T。

答案 - &gt;非密封类中的非照顾继承类型。

答案 4 :(得分:0)

简短的回答是覆盖泛型方法(或类)中类型T的变量,因为编译器没有明确地知道T是更多派生类型,因此无法使用更多派生类型(在我们的情况下Tint),因为T在运行时可以是任何其他更多派生类型。

答案很长:me变量的类型为ILovable<T>。现在me.Care函数需要ILovable<T>上指定的T类型的参数。 Care函数T之外的任何内容都可以是IEquatable<T>,因此int可以。但在函数内部,T必须只是T,而不是IEquatable<T>的另一种派生类型。否则会出现运行时错误,例如:

private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>
{
    var z = me.Care(1); 
}

...

Colour("");

现在,T在调用Colour("")时是字符串。因此meILovable<string>。因此,me.Care函数需要string作为参数,但提供的是int,这就是灾难。