programming multiple method interfaces genericas generic example clases c# .net class generics class-design

multiple - C#genéricos-¿Puedo hacer que T sea de una de dos opciones?



interfaces generics c# (7)

Supongamos que tengo la siguiente jerarquía de clases:

Class A {...} Class B : A {...} Class C : A {...}

Lo que tengo actualmente es

Class D<T> where T : A {...}

pero me gustaría algo de la forma

Class D<T> where T in {B,C}

Esto se debe a algún comportamiento extraño que no soy responsable de donde B y C tienen métodos comunes que no están en A, pero sería bueno poder llamarlos en D en T.

Nota: No tengo acceso a A, B o C para editarlos


¿B y C implementan la misma interfaz? Esa puede ser una mejor ruta.


Algunas opciones:

  1. Haga una interfaz IderivedFromA que contenga los métodos comunes de B y C
    Parece que esto es imposible por tu pregunta
  2. En D emite T para dynamic y llamar dinámicamente los métodos.
    La solución más fácil, si puedes usar .Net 4
  3. En la prueba D si usted trata con un B o C , emitir y llamar
    Será revisado por el compilador, y es posible desde .Net 2
  4. La respuesta de Dan Tao : Cree una implementación específica de D<T> para B y C , estos pueden llamar los métodos de B y C directamente. (No pensé en esto yo mismo).
    Solo funcionará si el "usuario-fuente" sabe que está tratando con B o C , y no usa el resumen A para usar D<A> . En su lugar, debe utilizar DB o DC . Pero creo que este es el caso, de lo contrario no necesitabas los genéricos.

Como no tiene acceso a la fuente, la única respuesta real (a menos que esté dispuesto a perder la seguridad mediante el uso de la dynamic ) es verificar explícitamente la B / C y la conversión.


Debe definir una interfaz para los métodos comunes que se encuentran en B y C (llamémosla Ibc), hacer que B y C implementen esta interfaz, y luego puede escribir:

Class D<T> where T : A, Ibc {...}


El lugar donde se restringe en C # no le permite especificar varias clases como una opción. Además, si especifica múltiples donde contiene, entonces ambos deben ser satisfechos. No hay lógica OR para la restricción. Aquí está la especificación: http://msdn.microsoft.com/en-us/library/bb384067.aspx

Las respuestas de Grzenio te parecen adecuadas. Extraiga el comportamiento común en la interfaz común para B y C. Luego, puede usar esa interfaz como una restricción.


Esto no es directamente posible.

Como otros sugieren, puede definir una interfaz e implementarla tanto en B como en C

Si esta no es una opción (por ejemplo, si estas clases están fuera de su control), lo que podría sugerir es esta: primero, comience con una clase abstracta que incluya toda la funcionalidad que puede lograr con cualquier T derivada de A Luego diga que tiene algunos métodos que existen tanto para B como para C que no forman parte de A En D puedes hacer que estos métodos abstractos sean implementados por subclases:

public abstract class D<T> where T : A { protected T _member; public void DoSomethingAllTsCanDo() { _member.DoSomething(); } public abstract void DoSomethingOnlyBAndCCanDo(); }

Luego puede heredar de la clase base para cada tipo B y C y anular los métodos abstractos para proporcionar la funcionalidad apropiada:

public class DB : D<B> { public override void DoSomethingOnlyBAndCCanDo() { _member.DoSomethingOnlyBCanDo(); } } public class DC : D<C> { public override void DoSomethingOnlyBAndCCanDo() { _member.DoSomethingOnlyCCanDo(); } }


Primero, si B y C tienen métodos comunes, es una falla de diseño que no comparten una interfaz. Dicho esto, puedes solucionarlo incluso sin tener acceso a B y C.
Es posible crear una interfaz común. Supongamos que usted tiene:

public class A { } public class B : A { public void Start() { } } public class C : A { public void Start() { } }

Puedes crear una interfaz común:

public interface IStartable { void Start(); }

Y úselo en clases derivadas de B y C:

public class BetterB : B, IStartable { } public class BetterC : C, IStartable { }

Es posible que no pueda lograrlo si obtiene las instancias B y C como están, pero se puede considerar si las crea. De hecho, con clases especializadas de B y C, puede usar la interfaz en lugar de D<T> .