2008-10-10 11 views
5

Tome este código no compilar por ejemplo:¿Es posible explotar una matriz para que sus elementos se puedan pasar a un método con la palabra clave params?

public string GetPath(string basefolder, string[] extraFolders) 
{ 
    string version = Versioner.GetBuildAndDotNetVersions(); 
    string callingModule = StackCrawler.GetCallingModuleName(); 
    return AppendFolders(basefolder, version, callingModule, extraFolders); 
} 
private string AppendFolders(params string[] folders) 
{ 
    string outstring = folders[0]; 
    for (int i = 1; i < folders.Length; i++) 
    { 
     string fixedPath = folders[i][0] == '\\' ? folders[i].Substring(1) : folders[i]; 
     Path.Combine(outstring, fixedPath); 
    } 
    return outstring; 
} 

Este ejemplo es una versión algo simplificada del código de prueba que estoy utilizando. Por favor, solo estoy interesado en soluciones que tengan que ver directamente con la palabra clave param. Sé cómo funcionan las listas y otras cosas similares.

¿Hay alguna manera de "explotar" la matriz extraFolders para que su contenido pueda pasarse a AppendFolders junto con otros parámetros?

+0

Solo para asegurarse de que entiendo, quiere que la matriz extraFolders se envíe al método AppendFolders como AppendFolders (extraFolders [0], extraFolders [1], ... etc etc.)? Interesante pregunta, me gustaría saber si eso es posible, aunque no veo cómo ... – BFree

+0

Eso es exactamente lo que quiero. –

+0

Su aclaración solo agrega más confusión. ¿Los elementos adicionales que se pasan son una parte importante de esto o no? Si no, la primera mitad de mi respuesta es lo que quieres. Si lo son, este es un caso muy especial, manejado por la segunda mitad de mi respuesta. –

Respuesta

1

Una opción es hacer que el parámetro params un object[]:

static string appendFolders(params object[] folders) 
{ return (string) folders.Aggregate("",(output, f) => 
         Path.Combine((string)output 
            ,(f is string[]) 
             ? appendFolders((object[])f) 
             : ((string)f).TrimStart('\\'))); 
} 

Si quieres algo más de tipo fuerte, otra opción es crear un tipo de unión aduanera con los operadores de conversión implícitas:

static string appendFolders(params StringOrArray[] folders) 
    { return folders.SelectMany(x=>x.AsEnumerable()) 
        .Aggregate("", 
         (output, f)=>Path.Combine(output,f.TrimStart('\\'))); 
    } 

    class StringOrArray 
    { string[] array; 

     public IEnumerable<string> AsEnumerable() 
     { return soa.array;} 

     public static implicit operator StringOrArray(string s) 
     { return new StringOrArray{array=new[]{s}};} 

     public static implicit operator StringOrArray(string[] s) 
     { return new StringOrArray{array=s};} 
    } 

En cualquier caso, esto será compilar:

appendFolders("base", "v1", "module", new[]{"debug","bin"}); 
1

Una solución rápida y sucia sería construir una cadena < > de los elementos y luego pasar eso (con ToArray()).

Tenga en cuenta que no es necesario que pruebe la barra diagonal inversa. Path.Combine maneja the dirty things rather fine.

+0

En algunos casos, no manejará la barra invertida correctamente. Terminé con una doble barra invertida en el pasado. ex. Blah \\ Blah –

+0

Entonces podría ser un error que puede archivar en http://connect.microsoft.com - y si desea seguir con la barra invertida, al menos use Path.DirectorySeparatorChar en lugar de un código rígido barra invertida. – OregonGhost

+0

* Path.Combine * tiene problemas si la segunda ruta comienza con una barra diagonal inversa. – brgerner

7

Sólo pásalo. El parámetro de carpetas es primero una matriz. la funcionalidad "params" es un poco de magia de compilación, pero no es necesaria.

AppendFolders(extraFolders); 

Ahora, esta es la instancia particular, primero tendrá que agregar algunas cosas a esa matriz.

List<string> lstFolders = new List<string>(extraFolders); 
lstFolder.Insert(0, callingModule); 
lstFolder.Insert(0, version); 
lstFolder.Insert(0, basefolder); 
return AppendFolders(lstFolders.ToArray()); 
+0

Supongo que el punto es que no se puede simplemente agregar cosas a una matriz :) – OregonGhost

1

Creo que la respuesta de OregonGhost es probablemente la que usted desea. Sólo para elaborar sobre ella, que está sugiriendo hacer algo como esto:

public string GetPath(string basefolder, string[] extraFolders) 
{ 
    string version = Versioner.GetBuildAndDotNetVersions(); 
    string callingModule = StackCrawler.GetCallingModuleName(); 

    List<string> parameters = new List<string>(extraFolders.Length + 3); 
    parameters.Add(basefolder); 
    parameters.Add(version); 
    parameters.Add(callingModule); 
    parameters.AddRange(extraFolders); 
    return AppendFolders(parameters.ToArray()); 
} 

Y no me refiero a esto como una lección sobre el uso de listas, al igual que una pequeña aclaración para cualquiera que pueda venir en busca de la solución en el futuro.

2

Voy a objetar el término "colapsar", ya que parece que realmente quieres "expandir". Y no estoy seguro de lo que quiere decir con soluciones que "tienen que ver directamente con la palabra clave params" y que "no le interesan las soluciones". Al final, debe pasar una serie de cadenas, que el compilador convertirá mágicamente en una matriz, o una matriz de cadenas directamente.Dicho esto, mi solución (sin cambiar la interfaz) sería algo como:

return AppendFolders(new string[] { basefolder, version, callingModule }.Concat(extraFolders).ToArray()); 

Editar:

Si bien no se puede agregar un operador a través de métodos de extensión, se puede hacer:

return AppendFolders(new string[] { baseFolder, callingModuleName, version }.Concat(extraFolders)); 

public static T[] Concat<T>(this T[] a, T[] b) { 
    return ((IEnumerable<T>)a).Concat(b).ToArray(); 
} 

Pero, si vamos a ir tan lejos - puede ser que también acaba de extender Lista <T> para manejar esta elegantemente:

return AppendFolders(new Params<string>() { baseFolder, callingModuleName, version, extraFolders }); 

class Params<T> : List<T> { 
    public void Add(IEnumerable<T> collection) { 
     base.AddRange(collection); 
    } 

    public static implicit operator T[](Params<T> a) { 
     return a.ToArray(); 
    } 
} 
+0

Esto está muy cerca de lo que quiero. Elegante y similar a lo que un compilador podría hacer. –

+0

Igualmente genial sería: nueva cadena [] {baseFolder, callingModuleName, version} + extraFolders –

Cuestiones relacionadas