以此非编译代码为例:
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;
}
这个例子是我正在使用的测试代码的简化版本。请,我只对直接与param关键字有关的解决方案感兴趣。我知道列表和其他类似的东西是如何工作的。
有没有办法“爆炸”extraFolders数组,以便它的内容可以与其他参数一起传递给AppendFolders?
答案 0 :(得分:7)
传递它。 folders参数首先是一个数组。 “params”功能有点编译魔术,但并不是必需的。
AppendFolders(extraFolders);
现在,在这个特殊情况下,你必须首先向该数组添加一些东西。
List<string> lstFolders = new List<string>(extraFolders);
lstFolder.Insert(0, callingModule);
lstFolder.Insert(0, version);
lstFolder.Insert(0, basefolder);
return AppendFolders(lstFolders.ToArray());
答案 1 :(得分:2)
我会用“崩溃”一词来狡辩,因为看起来你真的想“扩大”。而且我不确定解决方案是什么意思“与params关键字直接相关”以及“你对解决方法不感兴趣”。最后,你要么必须传递一些字符串 - 编译器将神奇地打包成一个数组 - 或直接传递一个字符串数组。话虽这么说,我的解决方案(不改变界面)会像:
return AppendFolders(new string[] { basefolder, version, callingModule }.Concat(extraFolders).ToArray());
编辑:
虽然您无法通过扩展方法添加运算符,但您可以执行以下操作:
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();
}
但是,如果我们要走那么远 - 也许只是扩展List&lt; T&gt;优雅地处理这个问题:
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();
}
}
答案 2 :(得分:1)
快速而肮脏的解决方案是构建List&lt; string&gt;从项目中传递(使用ToArray())。
请注意,您无需测试反斜杠。 Path.Combine处理the dirty things rather fine。
答案 3 :(得分:1)
我认为OregonGhost的回答可能就是您想要的方式。只是要详细说明,他建议做这样的事情:
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());
}
我并不是说这是关于如何使用列表的一个教训,只是为可能在将来寻找解决方案的任何人做一点澄清。
答案 4 :(得分:1)
一种选择是将params
参数设为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('\\')));
}
如果你想要更强类型的东西,另一种选择是用隐式转换运算符创建自定义联合类型:
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};}
}
在任何一种情况下,将编译:
appendFolders("base", "v1", "module", new[]{"debug","bin"});