Sospecho que la respuesta es no, pero me gustaría saber si es posible hacer algo como esto:¿Es posible restringir un parámetro de tipo de método genérico de C# como "asignable desde" el parámetro de tipo de clase que contiene?
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TSomeInterface>()
// This doesn't compile.
where TSomeClass : TSomeInterface
{
//...
}
}
Lo que quiero decir para indicar en el ejemplo anterior (que no funciona) es restringir TSomeInterface
tales que puede ser cualquier clase base, interfaz implementada o (si realmente desea obtener fantasía) conversión implícita de MyGenericClass
.
NOTA: sospecho que la razón por la que esto nunca fue implementado en C# es que las limitaciones genéricas no son realmente destinado a ser contratos de código, que es la forma en que estoy tratando de utilizarlos aquí. Realmente no me importa qué tipo es TSomeInterface
, siempre y cuando esté implementado por TSomeClass
.
Hasta ahora, he hackeado esto juntos:
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TIntermediateType, TSomeInterface>()
where TIntermediateType : TSomeClass, TSomeInterface
{
//...
}
}
Esto más o menos hace cumplir la restricción de que yo quiero (que TSomeClass
debe heredar de, o en el caso de una interfaz, implementar, TSomeInterface
), pero llamar es muy torpe, porque tengo que especificar TIntermediateType
(a pesar de que realmente lo quiero para evaluar contra TSomeClass
):
var myGenericInstance = new MyGenericClass<TSomeClass>();
myGenericInstance.MyGenericMethod(TSomeClass, TSomeInterface);
Además, el truco anterior se rompe debido a una persona que llama pudo en el o bien especifique una subclase de TSomeClass
como primer parámetro de tipo, donde solo la subclase implementa TSomeInterface
.
La razón por la que yo quiero hacer esto es que estoy escribiendo un patrón de fábrica de fluidez para un servicio WCF, y me como para evitar que la persona que llama (en tiempo de compilación) de tratar de crear un punto final con un contrato que la clase de servicio no implementa. Obviamente puedo verificar esto en tiempo de ejecución (WCF de hecho hace esto por mí), pero soy un gran admirador de la verificación en tiempo de compilación.
¿Hay una manera mejor/más elegante de lograr lo que busco aquí?
Esto es prácticamente imposible ya que está intentando mezclar genéricos con el tiempo de ejecución. – Polity
No, no lo soy. Solo estoy tratando de aplicar una restricción genérica que (por lo que puedo decir) el lenguaje C# no permite (restringir un parámetro de tipo tal que es una superclase o una interfaz implementada de un parámetro de tipo en la clase que lo contiene). –
Por lo que yo veo, intenta restringir la clase genérica en función de los datos de tipo que alimenta a un método.Si desea restringir el genérico de su clase, debe hacerlo a nivel de clase (lógicamente), de lo contrario no hay forma de que el compilador JIT cree una clase concreta. – Polity