Pregunta

Estoy desarrollando una aplicación en la que la necesidad de invocar un método de una clase genérica y no me importa el tipo de casos reales. Algo así como el siguiente código de Java:

public class Item<T>{
  private T item;

  public doSomething(){...}
}

...
public void processItems(Item<?>[] items){
 for(Item<?> item : items)
   item.doSomething();
}

En ese momento yo estaba en una prisa, así que he resuelto mi problema mediante la definición de una interfaz con los métodos que necesitaba para invocar e hice la clase genérica en práctica.

public interface IItem  
{
   void doSomething();
}

public class Item<T> : IItem {
  private T item;

  public void doSomething(){...}
}

...
public void processItems(IItem[] items)
{
 foreach(IItem item in items)
   item.doSomething();
}

Esta solución funciona bien, pero me gustaría saber cuál es la forma correcta para lograr el mismo comportamiento.

EDIT:

Se me olvidó referirse que la persona que llama de processItems no conoce los tipos reales. En realidad, la idea era que la matriz pasa como argumento a processItems podría contener tipos mezclados. Desde su no es posible tener una gama tan amplia en .Net, utilizando una clase de base genérico no o interfaz parece ser la única manera.

¿Fue útil?

Solución

La forma normal de hacer esto sería hacer el método genérico:

public void ProcessItems<T>(Item<T>[] items) {
  foreach(Item<T> item in items)
    item.DoSomething();
}

Suponiendo que el persona que llama sabe el tipo, la inferencia de tipos debería significar que no tienen que especificar explícitamente. Por ejemplo:

Item<int> items = new Item<int>(); // And then populate...
processor.ProcessItems(items);

Una vez dicho esto, la creación de una interfaz no genérico que especifica las operaciones de tipo-agnóstico puede ser útil también. Será mucho dependerá de su caso de uso exacto.

Otros consejos

veo que sólo desea invocar algún método sin parámetros ... ya hay un contrato para que:. Action

public void processItems(IEnumerable<Action> actions)
{
  foreach(Action t in actions)
    t();
}

Cliente:

List<Animal> zoo = GetZoo();
List<Action> thingsToDo = new List<Action>();
//
thingsToDo.AddRange(zoo
  .OfType<Elephant>()
  .Select<Elephant, Action>(e => e.Trumpet));
thingsToDo.AddRange(zoo
  .OfType<Lion>()
  .Select<Lion, Action>(l => l.Roar));
thingsToDo.AddRange(zoo
  .OfType<Monkey>()
  .Select<Monkey, Action>(m => m.ThrowPoo));
//
processItems(thingsToDo);

No hay ninguna manera se puede omitir parámetros de tipo genérico en aplicación .NET; Esto es por diseño. De hecho, esto sólo se puede lograr en Java debido a su aplicación tipo a base de borrado.

Sólo se puede utilizar una interfaz no genérico de base (piensa IEnumerable<T> y IEnumerable).

En relación con el puesto de Jon. haciendo que el método genérico (una plantilla) invalida el requisito para este tipo de funcionalidad (usando ). Siempre se puede alimentar a un tipo en una clase / función genérica y para los casos en los que no saben qué tipo necesitará usted puede hacer que el método infractor / clase genérica, así ... en última instancia, el usuario tiene que proporcionar un tipo al llamar tal función o el uso de una clase genérica, para el código para poder compilar ... de lo contrario obtendrá algunos errores de compilación.

He estado luchando con el mismo problema cuando se trataba de portar cosas de Java donde he tenido construcciones como

if (o instanceof Collection<?>) doSoemthing((Collection<?>)o);

Afortunadamente, resulta que un ICollection genérico es también un ICollection no genérico y si alguien necesita para el tratamiento de los elementos en los mismos objetos puros todavía es posible:

if (o is ICollection) DoSomething((ICollection)o);

De esa manera, ya que no importa el tipo real de los elementos de la colección todo lo que tenemos aquí son objetos. Una nota aquí:. Si la colección sostenía tipos primitivos (int o byte, por ejemplo), entonces autoboxing patadas en el que podría introducir penalización de rendimiento

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top