Ist es möglich, eine Anordnung zu explodieren, so dass seine Elemente auf ein Verfahren mit dem Schlüsselwort params übergeben werden können?

StackOverflow https://stackoverflow.com/questions/192715

Frage

Nehmen Sie diese nicht-Kompilierung Code zum Beispiel:

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;
}

Dieses Beispiel ist eine etwas vereinfachte Version des Testens Code ich verwende. Bitte, ich bin nur daran interessiert, Lösungen direkt mit dem param Stichwort zu tun. Ich weiß, wie Listen und andere ähnliche Dinge funktionieren.

Gibt es eine Möglichkeit, die extraFolders Array zu „explodieren“, so dass es kann Inhalte zusammen mit anderen Parametern in AppendFolders weitergegeben werden?

War es hilfreich?

Lösung

Eine Option ist die params Parameter eine object[] zu machen:

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('\\')));
 }

Wenn Sie etwas mehr stark typisierte wollen, eine weitere Option ist es, eine Zollunion Typen mit impliziter Konvertierung Betreibern zu erstellen:

  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};}
     }

In jedem Fall dieses kompilieren:

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

Andere Tipps

Just es passieren. Die Ordner Parameter ist ein Array zuerst. die „params“ Funktionalität ein wenig Compiler Magie ist, aber es ist nicht erforderlich.

AppendFolders(extraFolders);

Nun, es dieses particulat Beispiel, werden Sie einige Dinge zu diesem Array hinzufügen müssen, zuerst.

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

Ich werde mit dem Begriff „Zusammenbruch“ Wortklauberei, denn es wollen scheint Sie wirklich „erweitern“. Und ich bin nicht sicher, was Sie von Lösungen bedeuten „direkt mit params Stichwort zu tun haben“, und dass „Sie sind nicht daran interessiert, in Abhilfen“. Am Ende haben Sie entweder eine Reihe von Zeichenketten passieren -, die der Compiler wird auf magische Weise in ein Array-Paket - oder ein Array von Strings direkt. Davon abgesehen, ist meine Lösung (ohne die Schnittstelle zu ändern) so etwas wie gehen würde:

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

Edit:

Während Sie nicht einen Operator über Erweiterungsmethoden hinzufügen können, könnten Sie tun:

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();
}

Aber, wenn wir gehen, so weit gehen - vielleicht auch nur Liste erweitern zu handhaben elegant:

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();
    }
}

Eine schnelle und schmutzige Lösung wäre, eine Liste aus den Elementen zu bauen und dann passieren, dass (mit ToArray ()).

Beachten Sie, dass Sie nicht brauchen, für den umgekehrten Schrägstrich zu testen. Path.Combine Griffe die schmutzigen Dinge ziemlich fein .

Ich denke, OregonGhost Antwort ist wahrscheinlich der Weg Sie gehen wollen. Nur um näher auf sich, er ist darauf hindeutet, so etwas wie dies zu tun:

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());
}

Und ich meine nicht, dass als eine Lektion, wie Listen zu verwenden, ebenso wie eine wenig Klärung für alle, die entlang der Suche nach der Lösung in der Zukunft kommen können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top