是否可以分解数组,以便将其元素传递给带有 params 关键字的方法?

发布于 2024-07-06 16:35:06 字数 779 浏览 12 评论 0原文

以这个非编译代码为例:

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 中?

Take this non-compiling code for instance:

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

This example is a somewhat simplified version of testing code I am using. Please, I am only interested in solutions having directly to do with the param keyword. I know how lists and other similar things work.

Is there a way to "explode" the extraFolders array so that it's contents can be passed into AppendFolders along with other parameters?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

痕至 2024-07-13 16:35:06

就通过吧。 文件夹参数首先是一个数组。 “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());

Just pass it. The folders parameter is an array first. the "params" functionality is a little bit of compiler magic, but it's not required.

AppendFolders(extraFolders);

Now, it this particulat instance, you'll have to add some things to that array, first.

List<string> lstFolders = new List<string>(extraFolders);
lstFolder.Insert(0, callingModule);
lstFolder.Insert(0, version);
lstFolder.Insert(0, basefolder);
return AppendFolders(lstFolders.ToArray());
幻想少年梦 2024-07-13 16:35:06

我会对“崩溃”这个词争论不休,因为看起来你真的想“扩张”。 我不确定您所说的解决方案“与 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优雅地处理这个问题:

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

I'll quibble with the term "collapse", since it seems you really want to "expand". And I'm not sure what you mean by solutions "having directly to do with params keyword" and that "you're not interested in workarounds". In the end, you either have to pass a number of strings - which the compiler will magically package into an array - or an array of strings directly. That being said, my solution (without changing the interface) would go something like:

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

Edit:

While you can't add an operator via extension methods, you could do:

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

But, if we're going to go that far - might as well just extend List<T> to handle this elegantly:

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();
    }
}
眼中杀气 2024-07-13 16:35:06

一种选择是将 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"});

One option is to make the params parameter an 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('\\')));
 }

If you want something more strongly-typed, another option is to create a custom union type with implicit conversion operators:

  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 either case, this will compile:

appendFolders("base", "v1", "module", new[]{"debug","bin"});
捎一片雪花 2024-07-13 16:35:06

一个快速但肮脏的解决方案是构建一个 List从项目中获取,然后传递它(使用 ToArray())。

请注意,您不需要测试反斜杠。 Path.Combine 可以很好地处理脏东西

A quick and dirty solution would be to build a List<string> from the items and then pass that (with ToArray()).

Note that you don't need to test for the backslash. Path.Combine handles the dirty things rather fine.

雨后咖啡店 2024-07-13 16:35:06

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

我并不是说这是关于如何使用列表的课程,只是为将来可能寻找解决方案的任何人提供一点澄清。

I think OregonGhost's answer is probably the way you want to go. Just to elaborate on it, he's suggesting doing something like this:

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

And I don't mean that as a lesson on how to use Lists, just as a little clarification for anybody who may come along looking for the solution in the future.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文