I have an interface like this:
public interface IUser{
//some properties here
T ToDerived(User u);
}
I'm new to interface development, so here's what I'm trying to accomplish. I will have a base class
public class User
that does NOT implement the above interface. Then I will have a derived class
SalesUser : User, IUser
{
//no properties needed because they exist in the User class
SalesUser ToDerived(User u)
{
//code for converting a base User to a derived SalesUser
}
}
I would like to write the function for ToDerived(User u) in the SalesUser class, but in the interface, I do not know how to define this as the ToDerived method declaration that I have now in the interface is not compiling.
I hope this makes sense.
An interface name can also be used as a return type but the returned object must implement methods of that interface. The following Java program shows the implementation of a class name as a return type. In the above code, a SumResult class contains an addition method with class name as its return type.
T is called type parameter, which can be used as a type of fields, properties, method parameters, return types, and delegates in the DataStore class. For example, Data is generic property because we have used a type parameter T as its type instead of the specific data type. Note.
Generic interfaces can inherit from non-generic interfaces if the generic interface is covariant, which means it only uses its type parameter as a return value.
You can declare variant generic interfaces by using the in and out keywords for generic type parameters. ref , in , and out parameters in C# cannot be variant. Value types also do not support variance. You can declare a generic type parameter covariant by using the out keyword.
public interface IUser<T> where T : User
{
//some properties here
T ToDerived(User u);
}
SalesUser : User, IUser<SalesUser>
{
//no properties needed because they exist in the User class
SalesUser ToDerived(User u)
{
//code for converting a base User to a derived SalesUser
}
}
Not sure this is what you want, but I added a generic type constraint on the interface to ensure that the generic type is User
or inherits from it.
The answer by Oded solves the compilation problem, allowing you to define the ToDerived method that satisfies the interface. However, as I stated in the comment, I'm not exactly sure this is the best implementation.
The main problem I have with it is that conversion methods like this are normally needed in a static context. You don't have an instance of a SalesUser; you want one, and have a User, so you call the method in static context (SalesUser.ToDerived(myUser)
) and you get a SalesUser (the method would be more appropriately named FromUser() or similar). The method you specify in the interface requires you to already have a SalesUser in order to convert a User to a SalesUser. The only situation I can think of in which you really would need a pre-existing SalesUser is for a "partial clone"; you are making a new SalesUser instance using information from both the User passed in and from the SalesUser on which you are calling the method. In all other cases, you either don't need a SalesUser (conversions, which should be static as mentioned), or you don't need a User (a "clone" or "deep copy" method that produces a new instance with the same data as the instance on which you called the method).
Also, consumers of your class have to know that they must call ToDerived() in order to perform the conversion from a User to a SalesUser. Normally, a C# programmer would expect an explicit or implicit conversion to be available:
public class SalesUser
{
public static explicit operator (User user)
{
//perform conversion of User to SalesUser
}
}
//the above operator permits the following:
mySalesUser = (SalesUser)myUser;
... OR, failing a conversion operator, one would expect to be able to construct a SalesUser using a User:
public class SalesUser:IUser
{
public SalesUser(User user)
{
//initialize this instance using the User object
}
}
//the above allows you to do this:
mySalesUser = new SalesUser(myUser);
//and it also allows the definition of a method like this,
//which requires the generic to be an IUser and also requires a constructor with a User
public void DoSomethingWithIUser<T>(User myUser) where T:IUser, new(User)
{
//...which would allow you to perform the "conversion" by creating a T:
var myT = new T(myUser);
}
Now, static members do not satisfy interface definitions, and interfaces cannot define static members or constructor signatures. This tells me that the IUser interface should not try to define the conversion method; instead, methods that need an IUser of some sort can simply specify that, and the user can provide an implementation as necessary without the implementation needing to know it can convert to itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With