2012-04-09 15 views
6

que tienen una interfaz de esta manera:Cómo devolver el Tipo T en la interfaz en C#?

public interface IUser{ 
    //some properties here 

    T ToDerived(User u); 
} 

Soy nuevo interfaz de desarrollo, por lo que aquí es lo que estoy tratando de lograr. Tendré una clase base

public class User 

que NO implementa la interfaz anterior. A continuación, voy a tener una clase derivada

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 
    } 
} 

me gustaría escribir la función de ToDerived (usuario u) en la clase UsuariosVentas, pero en la interfaz, no sé cómo definir esto como la declaración del método ToDerived que ahora tengo en la interfaz no está compilando.

Espero que esto tenga sentido.

+1

[Aquí] (http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx) es un enlace a un blog de Eric que es relevante para esta pregunta. Incluye tanto un ejemplo que se parece mucho a la respuesta a continuación, y también trampas de usar este mecanismo de diseño. – Servy

Respuesta

14
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 
    } 
} 

No estoy seguro es lo que quiere, pero añade una restricción de tipo genérico en la interfaz para asegurarse de que el tipo genérico es User o herede de ella.

+0

Pásame, pero agregaría 'where T: User'. –

+0

@JimSchubert - Lo consideré y agregué mientras comentabas;) – Oded

+0

me ganaste dos veces :( –

0

Recuerde que una interfaz define una clase y sus miembros sin proporcionar ninguna implementación, puede crear una interfaz pero la interfaz debe tener la clase implementadora.

+0

¿Cómo responde esto la pregunta? – Oded

+0

Me gustaría escribir la función para ToDerived (Usuario u) en la clase SalesUser, pero en la interfaz, no sé cómo definir esto como la declaración del método ToDerived, no sé si estoy equivocado. –

3

La respuesta de Oded resuelve el problema de compilación, permitiéndole definir el método ToDerived que satisface la interfaz. Sin embargo, como dije en el comentario, no estoy exactamente seguro de que esta sea la mejor implementación.

El problema principal que tengo es que normalmente se necesitan métodos de conversión como este en un contexto estático. No tiene una instancia de SalesServer; usted quiere uno, y tiene un usuario, por lo que llama al método en contexto estático (SalesUser.ToDerived(myUser)) y obtiene un SalesUser (el método se llamaría más apropiadamente FromUser() o similar). El método que especifique en la interfaz requiere que ya tenga un SalesUser para convertir un usuario a SalesUser. La única situación que se me ocurre en la que realmente necesitaría un SalesUser preexistente es para un "clon parcial"; está realizando una nueva instancia de SalesUser utilizando información tanto del Usuario ingresado como del SalesUser en el que está llamando al método. En todos los demás casos, no necesita un SalesUser (conversiones, que deberían ser estáticas como se menciona), o no necesita un usuario (un método de "copia" o "copia profunda" que produce una nueva instancia con el mismos datos que la instancia en la que llamó al método).

Además, los consumidores de su clase tienen que saber que deben llamar a ToDerived() para realizar la conversión de un usuario a un usuario de ventas. Normalmente, un programador de C# sería esperar una conversión explícita o implícita a estar disponible:

public class SalesUser 
{ 

    public static explicit operator (User user) 
    { 
     //perform conversion of User to SalesUser 
    } 

} 

//the above operator permits the following: 
mySalesUser = (SalesUser)myUser; 

... O, en su defecto un operador de conversión, sería de esperar para poder construir un UsuariosVentas utilizando un usuario:

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

Ahora, los miembros estáticos no satisfacen las definiciones de interfaz, y las interfaces no pueden definir miembros estáticos o firmas de constructor. Esto me dice que la interfaz IUser no debe tratar de definir el método de conversión; en cambio, los métodos que necesitan un IUser de algún tipo pueden simplemente especificar eso, y el usuario puede proporcionar una implementación según sea necesario sin que la implementación necesite saber que puede convertirse a sí misma.

+0

Tiene razón, Oded resolvió el problema y respondió mi pregunta de la manera exacta que estaba buscando. Sin embargo, me gusta su explicación sobre esto y por qué no debería utilizar este patrón de diseño ya que este método en particular sería típicamente un método estático (con el que estoy de acuerdo). Cuando intento construir su ejemplo, tenga en cuenta que necesito que la clase SalesUser herede la clase de usuario base. public class SalesUser: User, IUser Entonces, cuando intento hacer esto, su método explícito no funciona. "no se permiten las conversiones definidas por el usuario hacia o desde una clase base". – jaressloo

+0

La "conversión" basada en el constructor debería funcionar. – KeithS

+0

Sí, la versión basada en el constructor es la ruta que optó por tomar por ahora. Sin embargo, intentaremos descubrir de otra manera para permitir una conversión explícita del Usuario base al SalesUser derivado. Gracias por tu ayuda. – jaressloo

Cuestiones relacionadas