2010-01-14 11 views
39

Veo este método Array.ConvertAll, pero requiere un Converter como argumento. No veo por qué necesito un convertidor, cuando ya he definido un implícito en mi clase:C# Cast Entire Array?

public static implicit operator Vec2(PointF p) 
    { 
     return new Vec2(p.X, p.Y); 
    } 

Estoy tratando de lanzar una serie de PointF s de una serie de Vec2 s. ¿Hay una buena manera de hacer esto? ¿O debería simplemente aspirar y escribir (otro) convertidor o recorrer los elementos?

+0

¡He aprendido algunas cosas interesantes a través de esta pregunta y sus respuestas! ¡Gracias! –

+3

@Terry: hago muchas preguntas triviales porque siempre me sorprenden las respuestas :) Es fácil resolver un problema, pero es difícil hacerlo elegantemente. – mpen

+0

Duplicado: http://stackoverflow.com/questions/944174/best-way-to-cast-from-animal-to-dog – Mikhail

Respuesta

69

La solución LINQ propuesta que usa Cast/'Seleccionar' está bien, pero como sabe que está trabajando con una matriz aquí, usar ConvertAll es bastante más eficiente e igual de simple.

var newArray = Array.ConvertAll(array, item => (NewType)item); 

Usando ConvertAll significa a) la matriz solamente se itera sobre una vez, no dos veces, b) la operación es más optimizado para matrices (no utiliza IEnumerator<T>).

No deje que el tipo Converter<TInput, TOutput> lo confunda, es simplemente un simple delegado, y por lo tanto puede pasarle una expresión lambda, como se muestra arriba.

+0

¡Funciona a la perfección! ¡Gracias! Pensé que tenía que definir el ''. – mpen

+3

No hay problema. Y sí, en C# 2.0 y antes de tener que definir un tipo, afortunadamente esos días ya no existen. – Noldorin

15

Cast no tiene en cuenta las conversiones implícitas definidas por el usuario, por lo que no puede convertir la matriz de esa manera. Se puede utilizar en lugar de seleccionar:

myArray.Select(p => (Vec2)p).ToArray(); 

O escribir un convertidor:

Array.ConvertAll(points, (p => (Vec2)p)); 

Este último es probablemente más eficiente como el tamaño del resultado se conoce de antemano.

+2

Mark es correcto, he eliminado mi respuesta. –

+0

Gracias por copiar mi respuesta como su edición ... – Noldorin

+0

Ya lo escribí antes de ver su publicación. Me pasó exactamente lo mismo hace una hora aquí: http://stackoverflow.com/questions/2067778/sql-for-delete-query/. Pasa algunas veces. No lo tome como algo personal, es solo una coincidencia que dos personas reciban exactamente la misma respuesta, aunque parezca que una copió a la otra. –

19

como una actualización a esta vieja pregunta, ahora se puede hacer:

myArray.Cast<Vec2>().ToArray(); 

donde miMatriz contiene los objetos de origen, y Vec2 es el tipo que desee para echar a.

+0

Muy elegante, gracias. – Nyerguds

+1

Espacio de nombres requerido: using System.Linq –