2011-02-22 7 views
13

Yo uso Microsoft.Office.Interop.Excel Me devuelven una matriz 2D de tipo object[,] que contiene double para elementos. Tenga en cuenta que el límite inferior del índice es 1 en lugar del predeterminado 0, pero puedo manejarlo fácilmente.¿Cómo puedo subir rápidamente el objeto [,] al doble [,]?

¿Cómo puede bien convertir la matriz en double[,] usando .NET 3.5. (bien quiero decir conciso, o compacto).

Tenga en cuenta que

double[] values_2 = values.Cast<double>().ToArray(); 

funciona, pero se aplana por matriz en una estructura 1D.

+0

No hay una manera "rápida" de hacerlo. Tienes que copiar todos los datos en una nueva matriz si eso es lo que quieres. – Gabe

+0

Tenía miedo de eso. ¿Qué pasa con '.NET 4.0'? ¿Alguna vez habrá una forma segura de hacer Office Interop? – ja72

+1

rápidamente como en "sin CPU" o tan rápido como en "declaración de una línea" – rene

Respuesta

27
object[,] src = new object[2, 3]; 

// Initialize src with test doubles. 
src[0, 0] = 1.0; 
src[0, 1] = 2.0; 
src[0, 2] = 3.0; 
src[1, 0] = 4.0; 
src[1, 1] = 5.0; 
src[1, 2] = 6.0; 

double[,] dst = new double[src.GetLength(0), src.GetLength(1)]; 
Array.Copy(src, dst, src.Length); 
+0

¿Has probado esto? – Gabe

+0

@Gabe Sí, tengo. – Marlon

+5

Santa mierda que funcionó! Gracias. Nuevamente educado por SO. ¡Gracias! – ja72

3

No diría que hay una manera que es más rápida que otra, siempre y cuando no hagas nada estúpido. Diría que, si puedes, preséntalas cuando accedas a ellas en lugar de hacerlo por adelantado. Por supuesto, esto depende de cómo intentes acceder a ellos. Si vas a indexar en la matriz más de una vez, entonces el costo de unboxing puede comenzar a ser demasiado. Si solo está escaneando la matriz una vez, luego envíela sobre la marcha.

1

Aquí hay un par de problemas.

Primero, dado que double no es un tipo de referencia, debe guardarse en un objeto [], por lo que la única forma de obtener los valores es desvinculando los valores en un doble [] (copiar copia).

El otro problema es que en C#, las matrices son covariantes pero no contravariantes, puede asignar una matriz a una referencia de un tipo derivado más, no a uno de tipo derivado menos.

string[] strings = new string[10]; 
object[] objects = strings; // OK, covariant 
string[] strings2 = objects; // not OK, contravariant 
objects[0] = 10; // Compiles fine, runtime ArrayTypeMismatchException! 
1
Array.Copy(src, dst, src.Length); 

Este código va de error en su caso del valor en src es nulo. Dado que en el código anterior src tienen algún valor definido, funciona bien. Si el valor de src se establece dinámicamente y, por desgracia, si alguno de los valores es nulo, el código anterior no funcionará. El valor no se copiará con éxito.

2

Esto debería funcionar en la mayoría de los casos, pero puede arrojar una excepción si no asigna un delegado de conversión.

public static TResult[,] Convert<TSource, TResult>(
    this TSource[,] array, Func<TSource, TResult> conversion = null) { 

     if(array == null) throw new ArgumentNullException("array"); 

     if (conversion == null) { 
      var resultType = typeof(TResult); 
      conversion = source => (TResult)System.Convert.ChangeType(source, resultType); 
     } 

     var width = array.GetLength(1); 
     var height = array.GetLength(0); 
     var result = new TResult[height, width]; 

     for (int i = 0; i < height; ++i) 
      for (int j = 0; j < width; ++j) 
       result[i, j] = conversion(array[i, j]); 

     return result; 
    } 
+0

Gracias pero hacer un elemento por conversión de elemento no es muy eficiente y definitivamente no es una solución _nice_. Aunque es bueno tener esto aquí para la posteridad. – ja72

+0

Estoy de acuerdo, es un poco feo, pero debería ser útil en una gama más amplia de circunstancias que solo tratar con las matrices de objetos de Excel. El comportamiento predeterminado es ciertamente lento, pero pasar a un delegado apropiado puede acelerar mucho las cosas. – JamesFaix

+0

La solución aceptada hace el trabajo bien, sin una mano. – ja72

Cuestiones relacionadas