简体   繁体   English

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

[英]Interface using generics “Cannot implicitly convert type”

If i have a class which accepts a generic type derived from IUser, how can i avoid this error message 如果我有一个接受从IUser派生的泛型类型的类,如何避免此错误消息

Cannot implicitly convert type ElimCMS.Service.Users.someclass<ElimCMS.DataModel.Users.User> to ElimCMS.Service.Users.Isomeclass<ElimCMS.DataModel.Users.IUser> . 无法将类型ElimCMS.Service.Users.someclass<ElimCMS.DataModel.Users.User>隐式转换为ElimCMS.Service.Users.Isomeclass<ElimCMS.DataModel.Users.IUser> An explicit conversion exists (are you missing a cast?) 存在显式转换(您是否缺少演员表?)

Example

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

This happens because generics which have different types are not compatible with eachother. 发生这种情况是因为具有不同类型的泛型彼此不兼容。 To get around this, you can declare your generic parameter to Isomeclass to be covariant using 为了解决这个问题,您可以使用以下方法将Isomeclass的通用参数声明为协变的

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

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

However, this will break the test method since it will no longer be type safe. 但是,这将破坏test方法,因为它将不再是类型安全的。 To get around this you can change the paramter user type to IUser and it will work as before. 为了解决这个问题,您可以将参数user类型更改为IUser ,它将像以前一样工作。

This is dependent on the version of C# that you are using. 这取决于您使用的C#版本。 For some older versions generics cannot be declared as covariant, which means you have to change the assignment target to be of the same type as the object you assign to it. 对于某些较旧的版本,无法将泛型声明为协变,这意味着您必须将分配目标更改为与分配给它的对象相同的类型。

Isomeclass<ElimCMS.DataModel.Users.IUser> and someclass<ElimCMS.DataModel.Users.User> are not assignment-compatible. Isomeclass<ElimCMS.DataModel.Users.IUser>someclass<ElimCMS.DataModel.Users.User>不兼容。 In fact, Isomeclass<ElimCMS.DataModel.Users.IUser> and Isomeclass<ElimCMS.DataModel.Users.User> cannot be assigned to each other. 实际上, Isomeclass<ElimCMS.DataModel.Users.IUser>Isomeclass<ElimCMS.DataModel.Users.User>彼此分配。

As you want to use the type specified by a type parameter TUser both as an input and an output parameter, you cannot declare the type argument as covariant or contravariant, so the only solution while keeping the current method signatures in your interface/class seems to be to type your list instance to IUser : 由于要同时使用类型参数TUser指定的类型作为输入参数和输出参数,因此无法将类型参数声明为协变或逆变,因此在接口/类中保留当前方法签名的唯一解决方案似乎是将您的列表实例键入IUser

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

or to type your list variable to User : 或将列表变量输入User

 Isomeclass<ElimCMS.DataModel.Users.User> servicetest

Change your declaration 更改您的声明

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

to

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

and redefine the test method appropriately in someclass<TUser> to match. 并在someclass<TUser>适当地重新定义test方法以进行匹配。

You can do this if you're using C# 4 (Visual Studio 2010) or greater. 如果您使用的是C#4(Visual Studio 2010)或更高版本,则可以执行此操作。 That'll get you what you need. 那将为您提供所需的东西。 If you are using prior versions, well, you'll have to revert to object and do some casting. 如果您使用的是以前的版本,那么您必须还原为object并进行一些转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM