Cannot pass variable of type conforming to generic constraint

蹲街弑〆低调 提交于 2020-01-04 02:53:09

问题


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

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

Say I have the above. Now below function fails:

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

What's failing the above piece of code? ILovable<T> has a Care function which intakes a T which is IEquatable<T>. In the above function I'm calling the same Care function and passing T which is int type. int is after all IEquatable<int>.

What am I doing wrong? Is there any work around to get it fixed?


回答1:


Your method signature does not specify a ILovable<int>, it specifies an ILovable<T>. This, for example, would work:

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

The problem is the compiler doesn't know that T is an 'int' in your example; it could be any type that meets the constraint. Here is another way that would work:

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);



回答2:


The error I get is:

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

I'm pretty sure this is because you are defining me as an ILovable<T>. Therefore, it doesn't automatically resolve to the Me type where int is defined as T.

This will fix the error because Me defines T as an int:

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



回答3:


Well that's because method Colour says that there will be parameter of type ILovable< T > whereas T would be resolved later, so at compile time either I tell method that T is int type.

So either you pass ILovable as parameter and grantee that T is int

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

or pass type Me directly

void Colour<T>(Me me)

Because otherwise me.Care is expecting type T not int as specific




回答4:


Change following

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

To

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

and above will work.


Now the mystry portion

You are getting error in following

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

because Care is expecting T, and you are providing int.
It is same as

Care((T)1).

or

 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

To make above work, T has to int. To make it so, Colur method syntax should be like

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

If you want to pass string to Care, T should be string.

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

Now if we have to fix T then question arises why T is required at all in Colour definition.

Answer -> For non taking care of inheritance type in non sealed class.




回答5:


The short answer is overriding variable of type T inside a generic method (or class) with a more derived type is not possible since compiler doesn't explicitly know T is that more derived type (in our case T is int), because T can be any other more derived type at run time.

Long answer: me variable is of type ILovable<T>. Now me.Care function is expecting parameter of type that is specified on ILovable<T> which is T. Outside the Care function T can be anything that is IEquatable<T>, so int is ok. But inside the function, T has to be just T and not another derived type of IEquatable<T>. Otherwise there will be runtime error for scenarios like this:

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

...

Colour("");

Right now, T is string when calling Colour(""). So me is ILovable<string>. So me.Care function expects a string as parameter but provided is an int and that is disaster.



来源:https://stackoverflow.com/questions/14082431/cannot-pass-variable-of-type-conforming-to-generic-constraint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!