Reputation: 149
If i have a class which accepts a generic type derived from IUser, how can i avoid this error message
Cannot implicitly convert type
ElimCMS.Service.Users.someclass<ElimCMS.DataModel.Users.User>
toElimCMS.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>();
Upvotes: 1
Views: 3353
Reputation: 20157
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.
You can do this if you're using C# 4 (Visual Studio 2010) or greater. 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.
Upvotes: 1
Reputation: 5744
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
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. To get around this you can change the paramter user
type to IUser
and it will work as before.
This is dependent on the version of C# that you are using. 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.
Upvotes: 5
Reputation: 20780
Isomeclass<ElimCMS.DataModel.Users.IUser>
and someclass<ElimCMS.DataModel.Users.User>
are not assignment-compatible. In fact, Isomeclass<ElimCMS.DataModel.Users.IUser>
and Isomeclass<ElimCMS.DataModel.Users.User>
cannot be assigned to each other.
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
:
new someclass<ElimCMS.DataModel.Users.IUser>();
or to type your list variable to User
:
Isomeclass<ElimCMS.DataModel.Users.User> servicetest
Upvotes: 2