以这个非编译代码为例:
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;
}
Run Code Online (Sandbox Code Playgroud)
这个例子是我正在使用的测试代码的简化版本.请,我只对直接与param关键字有关的解决方案感兴趣.我知道列表和其他类似的东西是如何工作的.
有没有办法"爆炸"extraFolders数组,以便它的内容可以与其他参数一起传递到AppendFolders?
背景
我有一个容器类,它在内部使用vector <std :: string>.我已经为这个包装类提供了一个方法AddChar(std :: string),它对内部向量执行push_back().在我的代码中,我必须在容器中添加多个项目.为此,我必须使用
container.AddChar("First");
container.AddChar("Second");
Run Code Online (Sandbox Code Playgroud)
这使代码更大.因此,为了使它更容易,我计划重载operator <<.这样我就可以写了
container << "First" << "Second"
Run Code Online (Sandbox Code Playgroud)
并且两个项目将被添加到底层矢量.
这是我用于此的代码
class ExtendedVector
{
private:
vector<string> container;
public:
friend ExtendedVector& operator<<(ExtendedVector& cont,const std::string str){
cont.AddChar(str);
return cont;
}
void AddChar(const std::string str)
{
container.push_back(str);
}
string ToString()
{
string output;
vector<string>::iterator it = container.begin();
while(it != container.end())
{
output += *it;
++it;
}
return output;
}
};
Run Code Online (Sandbox Code Playgroud)
它按预期工作.
问题
有什么想法吗?
编辑
在听到优秀的评论之后,我决定不要超载<<因为它在这里没有意义.我删除了运算符重载代码,这是最终代码.
class ExtendedVector
{
private: …
Run Code Online (Sandbox Code Playgroud) 我刚注意到一个带有重载决策的奇怪行为.
假设我有以下方法:
public static void DoSomething<T>(IEnumerable<T> items)
{
// Whatever
// For debugging
Console.WriteLine("DoSomething<T>(IEnumerable<T> items)");
}
Run Code Online (Sandbox Code Playgroud)
现在,我知道通常会使用少量显式参数调用此方法,因此为方便起见,我添加了此重载:
public static void DoSomething<T>(params T[] items)
{
// Whatever
// For debugging
Console.WriteLine("DoSomething<T>(params T[] items)");
}
Run Code Online (Sandbox Code Playgroud)
现在我尝试调用这些方法:
var items = new List<string> { "foo", "bar" };
DoSomething(items);
DoSomething("foo", "bar");
Run Code Online (Sandbox Code Playgroud)
但在这两种情况下,params
都会调用重载.我希望IEnumerable<T>
在a的情况下调用重载List<T>
,因为它似乎是一个更好的匹配(至少对我而言).
这种行为是否正常?谁能解释一下呢?我在MSDN文档中找不到任何关于它的明确信息......这里涉及的重载决策规则是什么?
c# generics type-inference params-keyword overload-resolution
据我所知,params
只是语法糖,"引擎盖下"只是给你一个你指定类型的数组.
首先,你什么时候使用它?
其次,为什么要使用它而不是仅仅声明一个数组参数?
最近,我发现索引器可以接受一组参数params
:
public class SuperDictionary<TKey, TValue>
{
public Dictionary<TKey, TValue> Dict { get; } = new Dictionary<TKey, TValue>();
public IEnumerable<TValue> this[params TKey[] keys]
{
get { return keys.Select(key => Dict[key]); }
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您将能够:
var sd = new SuperDictionary<string, object>();
/* Add values */
var res = sd["a", "b"];
Run Code Online (Sandbox Code Playgroud)
但是,我从未在.NET Framework或任何第三方库中遇到过这种用法.为什么要实施?能够引入params
索引器的实际用法是什么?
如您所知,C#通过params
关键字支持可变方法:
int Add(params int[] xs) {
return xs.Sum();
}
Run Code Online (Sandbox Code Playgroud)
然后可以使用您喜欢的任意数量的参数调用它:
Add(1);
Add(1, 2);
Add(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
但是说我想Add
使用int
s 1的数组调用.这是可能的以及如何(最好没有反思)?我尝试了以下但他们给出了语法错误(语法纯粹是猜测):
var xs = new[] { 1, 2, 3 };
Add(xs...); // doesn't work; syntax error
Add(params xs); // doesn't work; syntax error
Run Code Online (Sandbox Code Playgroud)
1我的实际用例不同,但我认为这个例子不那么复杂.
好的,回到基础.我想知道如何使用params
参数正确地重载方法.
这是我的情景.我从我的常规方法开始:
public void MyMethod(MyObject mo)
{
// method body
}
Run Code Online (Sandbox Code Playgroud)
我为它创建了一个重载,如下所示:
public void MyMethod(MyObject mo, params string[] fields)
{
// new method body
MyMethod(mo);
}
Run Code Online (Sandbox Code Playgroud)
显而易见的目的是MyMethod(new MyObject());
执行原始方法并MyMethod(new MyObject(), "field0"/*, etc...*/);
执行重载方法.但这不是我发现的情况.
实际发生的是MyMethod(new MyObject());
执行重载方法!
我不明白.在这种情况下,我将如何执行原始方法?
好的,所以这里是产生所描述行为的实际代码.
Class1Base.cs:
public class Class1Base
{
public virtual void MyMethod(MyObject ob)
{
Console.WriteLine("Called Class1Base");
}
}
Run Code Online (Sandbox Code Playgroud)
将Class1.cs:
public class Class1 : Class1Base
{
public override void MyMethod(MyObject ob)
{
Console.WriteLine("called overridden method");
}
public void MyMethod(MyObject ob, …
Run Code Online (Sandbox Code Playgroud)