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?
By using the params keyword, you can specify a method parameter that takes a variable number of arguments. The parameter type must be a single-dimensional array. No additional parameters are permitted after the params keyword in a method declaration, and only one params keyword is permitted in a method declaration.
Params is an important keyword in C#. It is used as a parameter which can take the variable number of arguments. Important Point About Params Keyword : It is useful when programmer don't have any prior knowledge about the number of parameters to be used.
Parameters and Arguments They are specified after the method name, inside the parentheses. You can add as many parameters as you want, just separate them with a comma.
C# Parameter array is declared with the params modifier. Parameter type must be declared as an array. Must be of a single-dimensional Array type. Single params array per method is allowed. Must be the last argument in the method's parameter list.
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());
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();
}
}
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"});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With