Método genérico restricción de tipo múltiple (OR)

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 asegurar que “U” sea un IEnumerable .

 public T DoSomething(U arg) where U : IEnumerable { return arg.First(); } 

Encontré un código más que permitió agregar múltiples restricciones de tipo, tales como:

 public void test(string a, T arg) where T: ParentClass, ChildClass { //do something } 

Sin embargo, este código parece hacer cumplir que arg debe ser tanto 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(string a, T arg) where T: string OR Exception { //do something } 

¡Tu ayuda es apreciada como siempre!

Eso no es posible. Sin embargo, puede definir sobrecargas para tipos específicos:

 public void test(string a, string arg); public void test(string a, Exception arg); 

Si esos son parte de una clase genérica, serán preferibles a la versión genérica del método.

La respuesta de Botz es 100% correcta, aquí hay una breve explicación:

Cuando está escribiendo un método (genérico o no) y declara los tipos de parámetros que le lleva el método, está definiendo un contrato:

Si me das un objeto que sabe cómo hacer el conjunto de cosas que el Tipo T sabe cómo hacerlo, puedo entregar ‘a’: un valor de retorno del tipo I declarar, o ‘b’: algún tipo de comportamiento que utiliza ese tipo.

Si intentas darle más de un tipo a la vez (al tener un o) o intentas que devuelva un valor que podría ser más de un tipo, ese contrato se vuelve borroso:

Si me das un objeto que sepa saltar la cuerda o sepa cómo calcular pi hasta el decimoquinto dígito, devolveré un objeto que puede ir a pescar o quizás mezclar concreto.

El problema es que cuando IJumpRope al método no tienes idea si te han dado un IJumpRope o un PiFactory . Además, cuando avanzas y usas el método (suponiendo que lo hayas comstackdo mágicamente), no estás seguro si tienes un Fisher o AbstractConcreteMixer . Básicamente hace que todo sea más confuso.

La solución a su problema es una de dos posibilidades:

  1. 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 progtwigción esto se conoce como Sobrecarga del método.

  2. Defina una clase base o interfaz que sepa cómo hacer todas las cosas que necesita para el método y haga que un solo método tome ese tipo. Esto puede implicar cerrar una string y Exception en una clase pequeña para definir cómo planea asignarlos a la implementación, pero luego todo es súper claro y fácil de leer. Podría venir, dentro de cuatro años, leer su código y entender fácilmente lo que está pasando.

Lo que elijas depende de cuán complicadas serían las opciones 1 y 2 y cuán extensible debe ser.

Entonces, para su situación específica, me voy a imaginar que está sacando un mensaje o algo de la excepción:

 public interface IHasMessage { string GetMessage(); } public void test(string a, IHasMessage arg) { //Use message } 

Ahora todo lo que necesita son métodos que transforman una string y una Exception a un IHasMessage. Muy fácil.

Si ChildClass significa que se deriva de ParentClass, puede escribir lo siguiente para aceptar ParentClass y ChildClass;

 public void test(string a, T arg) where T: ParentClass { //do something } 

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;

 public interface ICommonInterface { string SomeCommonProperty { get; set; } } public class AA : ICommonInterface { public string SomeCommonProperty { get;set; } } public class BB : ICommonInterface { public string SomeCommonProperty { get; set; } } 

entonces puedes escribir tu función genérica como;

 public void Test(string a, T arg) where T : ICommonInterface { //do something }