2011-11-30 10 views
5

Tengo una interfaz llamada Identifiable<TId> que contiene un único Id de propiedad del tipo dado. Quiero crear una clase genérica que tome uno de estos como un parámetro de tipo. Debe ser genérico porque quiero devolver el tipo concreto, llamar a otros métodos genéricos desde dentro y usar cosas como typeof(T).¿Es posible implementar esta interfaz genéricamente para que se le pueda pasar solo un parámetro de tipo?

Esto funciona bien:

public class ClassName<T, TId> where T : Identifiable<TId> 

problema es que código de llamada tiene que pasar en dos tipos. p.ej. new ClassName<Person, int>()

Me pregunto si en .NET 3.5 hay alguna forma de escribir esto para que TId pueda inferirse por T? ¿Permitir que la persona que llama simplemente haga new ClassName<Person>()?

+1

Tal vez podría mostrar un ejemplo un poco más detallada por lo que podría sea ​​evidente lo que está tratando de hacer y por qué. – deepee1

Respuesta

2

Por la naturaleza de su pregunta, supongo que su ClassName no se basa en ningún método identificable que requiera TId (de lo contrario necesitaría el tipo). Si ese es el caso, una solución común en este caso es crear una interfaz base no genérica, con todos los métodos que no requieren el tipo TId. Entonces usted tiene:

interface Identifiable<TId> : Identifiable //Not a standard interface name, btw 

y su restricción se convierte en:

public class ClassName<T> where T : Identifiable 

Suponiendo que en realidad no necesita el tipo TID, pero está buscando para simplificar la sintaxis de la construcción, una opción, si su constructor toma una instancia de Identificable (como Persona en su ejemplo) es para cambiar el constructor a un método de fábrica:

public static ClassName<T, TId> FromIdentifiable<T,TId>(T identifiable) where T: Identifiable<TId> 

Lo anterior debería permitirle al compilador inferir los tipos y darle una sintaxis más corta, según el tipo del parámetro.

1

No. Debe proporcionar un parámetro de tipo para Identifiable<>; ¿Cómo pudiste hacer eso sin declarar el parámetro en la declaración de clase:

public class ClassName<T> where T : Identifiable<?WhatDoWePutHere?> 
1

yo sepa, no es posible con la cláusula where. Es posible que desee utilizar los contratos de código (por ejemplo, en .Net 4) y añadir

Contract.Requires(T is Identifiable<TId>); 

a su código. No sé si hay alguna forma de hacer cumplir esto en .Net 3.5.

1

Si la mayoría de los usos de su clase serán del tipo ClassName<Person, int> donde el tipo T (Persona) es lo que varía la mayor parte del tiempo pero el tipo TId es casi siempre int, podría proporcionar una clase parcialmente resuelta que suministre el TId tipo, pero mantiene el tipo T sin consolidar. La principal desventaja de esto es que tendrá múltiples clases que deben tener diferentes nombres.

public class BaseClassName<T, TId> where T: Identifiable<TId> 
{ } 

public class ClassName<T> : ClassName<T, int> 
{ } 

var x = new ClassName<Person>(); 

Para el caso menos frecuente cuando no se desea int como el TID, entonces la clase aridad 2 es todavía disponibles:

var y = new BaseClassName<Person, int>() 
Cuestiones relacionadas