使用泛型的接口“无法隐式转换类型”

时间:2012-08-03 13:25:42

标签: c# generics

如果我有一个类接受从IUser派生的泛型类型,我该如何避免此错误消息

  

无法将ElimCMS.Service.Users.someclass<ElimCMS.DataModel.Users.User>类型隐式转换为ElimCMS.Service.Users.Isomeclass<ElimCMS.DataModel.Users.IUser>。存在显式转换(您是否错过了演员?)

实施例

   public interface Isomeclass<TUser>
   where TUser : class, IUser
   {

    string test(TUser user);
    TUser returnUser();
   }

   public class someclass<TUser> : Isomeclass<TUser>
   where TUser : class, IUser, new()
   {
    public string test(TUser user)
    {
        string email = user.EMail;
        user.EMail = "changed:" + email;

        return email;
    }


    public TUser returnUser()
    {
        throw new NotImplementedException();
    }
}

 Isomeclass<ElimCMS.DataModel.Users.IUser> servicetest = new someclass<ElimCMS.DataModel.Users.User>();

3 个答案:

答案 0 :(得分:5)

这是因为具有不同类型的泛型彼此不兼容。要解决此问题,您可以使用

将通用参数声明为Isomeclass以协变
public interface Isomeclass<out TUser>
   where TUser : class, IUser
{

    string test(TUser user);
    TUser returnUser();
}

但是,这会破坏test方法,因为它不再是类型安全的。要解决此问题,您可以将参数user类型更改为IUser,它将像以前一样工作。

这取决于您使用的C#版本。对于某些旧版本,泛型不能声明为协变,这意味着您必须将赋值目标更改为与分配给它的对象相同的类型。

答案 1 :(得分:2)

Isomeclass<ElimCMS.DataModel.Users.IUser>someclass<ElimCMS.DataModel.Users.User>不兼容分配。实际上,Isomeclass<ElimCMS.DataModel.Users.IUser>Isomeclass<ElimCMS.DataModel.Users.User>无法相互分配。

由于您希望使用类型参数TUser指定的类型作为输入和输出参数,因此您不能将类型参数声明为协变或逆变,因此保留当前方法签名的唯一解决方案在你的接口/类中似乎是要将列表实例键入IUser

new someclass<ElimCMS.DataModel.Users.IUser>();

或将列表变量键入User

 Isomeclass<ElimCMS.DataModel.Users.User> servicetest

答案 2 :(得分:1)

更改声明

public interface Isomeclass<TUser> where TUser : class, IUser
{
    string test(TUser user);
    TUser returnUser();
}

public interface Isomeclass<out TUser> where TUser : class, IUser
{
    string test(IUser user);
    TUser returnUser();
}

并在test中相应地重新定义someclass<TUser>方法以匹配。

如果您使用的是C#4(Visual Studio 2010)或更高版本,则可以执行此操作。这将为您提供所需的一切。如果您使用的是先前版本,那么您必须恢复为object并进行投射。