Al leer esto , aprendí que era posible permitir que un método aceptara parámetros de múltiples tipos al convertirlo en un método genérico. En el ejemplo, el siguiente código se usa con una restricción de tipo para garantizar que "U" sea un IEnumerable<T>
.
public T DoSomething<U, T>(U arg) where U : IEnumerable<T>
{
return arg.First();
}
Encontré más código que permitía agregar restricciones de tipo múltiple, como:
public void test<T>(string a, T arg) where T: ParentClass, ChildClass
{
//do something
}
Sin embargo, este código parece imponer que arg
debe ser un tipo de ParentClass
y ChildClass
. Lo que quiero hacer es decir que arg podría ser un tipo de ParentClass
o ChildClass
de la siguiente manera:
public void test<T>(string a, T arg) where T: string OR Exception
{
//do something
}
Su ayuda es apreciada como siempre!
c#
asp.net-mvc-3
types
Mansfield
fuente
fuente
where T : string
, ya questring
es una clase sellada . Lo único que podría hacer es definir las sobrecargasstring
yT : Exception
, como explica @ Botz3000 en su respuesta a continuación.arg
son los definidos porobject
, entonces, ¿por qué no simplemente eliminar los genéricos de la imagen y hacer el tipo dearg
object
? Que estas ganandoRespuestas:
Eso no es posible. Sin embargo, puede definir sobrecargas para tipos específicos:
Si son parte de una clase genérica, se preferirán a la versión genérica del método.
fuente
or
relación hace que las cosas, en general, sean útiles. Te tiene que hacer la reflexión de averiguar qué hacer y todo eso. (¡YUCK!)La respuesta de Botz es 100% correcta, aquí hay una breve explicación:
Cuando escribe un método (genérico o no) y declara los tipos de parámetros que toma el método, está definiendo un contrato:
Si intenta darle más de un tipo a la vez (con un o) o intenta que devuelva un valor que podría ser más de un tipo, el contrato se vuelve borroso:
El problema es que cuando entras en el método no tienes idea si te han dado un
IJumpRope
o unPiFactory
. Además, cuando continúas y usas el método (suponiendo que lo has compilado mágicamente) no estás realmente seguro de tener unFisher
o unAbstractConcreteMixer
. Básicamente hace que todo sea mucho más confuso.La solución a su problema es una de dos posibilidades:
Defina más de un método que defina cada posible transformación, comportamiento o lo que sea. Esa es la respuesta de Botz. En el mundo de la programación, esto se conoce como sobrecarga del método.
Defina una clase base o interfaz que sepa cómo hacer todas las cosas que necesita para el método y haga que un método tome solo ese tipo. Esto puede implicar envolver una
string
yException
en una pequeña clase para definir cómo se planea en el mapeo de ellos para la puesta en práctica, pero luego todo es super clara y fácil de leer. Podría venir, dentro de cuatro años, leer su código y comprender fácilmente lo que está sucediendo.El que elija depende de cuán complicadas serían las opciones 1 y 2 y de lo extensible que debe ser.
Entonces, para su situación específica, voy a imaginar que solo está sacando un mensaje o algo de la excepción:
Ahora todo lo que necesita son métodos que transforman una
string
y unaException
a una IHasMessage. Muy fácil.fuente
Si ChildClass significa que se deriva de ParentClass, puede escribir lo siguiente para aceptar ParentClass y ChildClass;
Por otro lado, si desea utilizar dos tipos diferentes sin relación de herencia entre ellos, debe considerar los tipos que implementan la misma interfaz;
entonces puedes escribir tu función genérica como;
fuente
Tan antigua como esta pregunta es, todavía recibo votos al azar sobre mi explicación anterior. La explicación sigue siendo perfectamente correcta, pero voy a responder por segunda vez con un tipo que me sirvió como un sustituto para los tipos de unión (la respuesta fuertemente tipada a la pregunta que C # no admite directamente como es). )
La clase anterior representa un tipo que puede ser cualquiera de TP o TA. Puede usarlo como tal (los tipos se refieren a mi respuesta original):
Notas importantes:
IsPrimary
primero.IsNeither
IsPrimary
oIsAlternate
.Primary
yAlternate
Either
cualquier lugar donde se espera uno. Si se hace pasar unaEither
en unaTA
, oTP
se espera, pero laEither
contiene el tipo incorrecto de valor que obtendrá un error de ejecución.Normalmente uso esto donde quiero que un método devuelva un resultado o un error. Realmente limpia ese código de estilo. También ocasionalmente ( rara vez ) uso esto como un reemplazo para las sobrecargas de métodos. Siendo realistas, este es un sustituto muy pobre para tal sobrecarga.
fuente