Pregunta

Disculpen si esto es una víctima, pero no era capaz de conseguir la combinación adecuada de palabras clave para filtrar por las diversas preguntas tipo de restricción y genéricos por ahí (ya que hay un montón).

Tengo dos interfaces - llamémosles Ionline y IOffline .

Están estrechamente relacionados en los contratos que describen casi idénticas, pero una de las diferencias clave entre ellos es el contexto en el que se utilizan las implementaciones concretas. No es exactamente mi situación, pero ilustra bien el problema.

Entonces tengo algunos métodos por ahí que van en contra de los ejecutores concretos de estas interfaces. A veces, estos métodos sólo quieren tratar con un tipo y no el otro.

Bastante simple:

public void DoStuff<T>(string foo) where T : IOnline {}

El golpeador está implementando el código para métodos que pueden operar en el tipo de SEA. Pensé que esto sería correcto, pero al leer el error de compilación, mi expectativa de que la restricción sería interpretado como "permite ningún tipo T que se utilizará genéricamente aquí si implementan Ionline O IOffline", en realidad se está interpretando como "Permitir cualquier tipo T para ser utilizado genéricamente aquí si implementan ambos".

public void DoStuff<T>(string foo) where T : IOnline, IOffline {}

Tratando de implementar dos métodos independientes con el mismo nombre pero diferentes limitaciones falla ya que no hay problemas de ambigüedad obvias - ESTAMOS no sobrecargando ya que la lista de parámetros es el mismo (ya que el comportamiento deseado es idéntica).

podría utilizar dos nombres diferentes para dos métodos diferentes, cada uno con la restricción apropiada, pero que parece kludgy y hace otras cosas aguas abajo para ser un dolor en el culo ... factible, pero no ideal.

Siento que debe haber algo que me falta aquí ... me siento perfectamente cómodo en la tierra genérica pero esta es la primera vez que he tenido para llevar a cabo lo que busco y me siento como si estuviera simplemente girando las ruedas de mi atm.

¿Fue útil?

Solución

El suministro de múltiples restricciones como en el segundo ejemplo es, en efecto aditivo. El página de MSDN de las limitaciones genéricas tiene un poco acerca de esto.

¿Se puede hacer que sus dos interfaces heredan de una interfaz de base, y restringir los métodos para el tipo de base?

Otros consejos

Esto no es tal vez una respuesta a su pregunta, pero de forma espontánea la sensación de que es posible que desee refactor sus interfaces. Desde su pregunta:

  

Están estrechamente relacionados en que   describir contratos casi idénticos,   pero una de las principales diferencias entre   ellos es el contexto en el que la   Se utilizarán las implementaciones concretas.

Mi punto de vista de las interfaces es que Son contratos . Definen cómo algo debe buscar , no exactamente como debe comportan ; esa es la tarea de la aplicación. Ahora, no tengo ninguna información sobre su aplicación o dominio del problema, pero probablemente tratar de pasar algún tiempo en identificar partes idénticas de esas interfaces y moverlos en una única interfaz, y sólo mantener una de las diferencias como interfaces separadas. De esa manera usted quizá podría desplazarse más allá de estos tipos de problemas más fácilmente.

Creo que la forma estándar de .NET para hacer esto es tener una interfaz que contiene tanto sus funciones Ionline y IOffline, y luego algunas propiedades que dicen que funciona realmente se implementa en una clase específica. Usted ve este patrón en varios lugares en .NET con cosas como un método Seek () que podría o no podría ser implementado y una propiedad canSeek que se puede probar.

No es quizás el diseño más limpio OO, pero funciona.

pierde parte de la en tiempo de compilación, pero no puedo ver ninguna manera a su alrededor ... Usted tiene que elegir cuál prefiere utilizar, (estoy suponiendo que su preferencia sería en línea):

public void DoStuff<T>(string foo)
{
    Type type = typeof(T);
    if(type.GetInterfaces().Contains(typeof(IOnline)))
         doStuffOnline<T>(foo);
    else if(type.GetInterfaces().Contains(typeof(IOffline)))
         doStuffOffline<T>(foo);
    else
         throw new Exception("T must implement either IOnline or IOffline");
}

private void doStuffOnline<T>(string foo){ // can assume T : IOnline }
private void doStuffOffline<T>(string foo){ // can assume T : IOffline }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top