正如标题所说,我需要知道...在方法参数中是否存在与java相对应的语法,例如
void printReport(String header, int... numbers) { //numbers represents varargs
System.out.println(header);
for (int num : numbers) {
System.out.println(num);
}
}
Run Code Online (Sandbox Code Playgroud)
(代码由维基百科提供)
与此问题类似,我想将可选参数与params关键字混合,这当然会产生歧义.不幸的是,创建重载的答案不起作用,因为我想利用调用者信息属性,如下所示:
public void Info(string message, [CallerMemberName] string memberName = "",
[CallerLineNumber] int lineNumber = 0, params object[] args)
{
_log.Info(BuildMessage(message, memberName, lineNumber), args);
}
Run Code Online (Sandbox Code Playgroud)
在没有可选参数的情况下创建重载会更改调用站点,从而阻止这些特定参数正常工作.
我找到了一个几乎可以工作的解决方案(虽然很难看):
public void Info(string message, object arg0, [CallerMemberName] string memberName = "",
[CallerLineNumber] int lineNumber = 0)
{
_log.Info(BuildMessage(message, memberName, lineNumber), arg0);
}
public void Info(string message, object arg0, object arg1, [CallerMemberName] string memberName = "",
[CallerLineNumber] int lineNumber = 0)
{
_log.Info(BuildMessage(message, memberName, lineNumber), arg0, arg1);
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是,如果为最后一个参数指定一个字符串,则重载决策假定您打算memberName在重载中显式指定需要较少的参数,这不是所需的行为.
有没有办法实现这一点(也许使用一些我没有学过的新属性?)或者我们是否只是达到了自动魔法编译器支持可以给我们的极限?
所以我看到有可能有一个方法签名,其中第一个参数提供默认值,第二个参数是params集合.
我看不到的是实际使用第一个参数的默认值的方法.
它可能吗?
示例方法:
void WaitAllTasks(string message = "Running Task.WaitAll", params Task[] tasks);
我最初尝试在调用方法时省略message参数,并尝试使用命名参数,这与params不兼容.
它编译,但是可以使用它吗?
我已经看过params参数的次数比我说的多,并且在不考虑它的意义的情况下总是将其删除.现在我已经了解了它的目的.我刚学到的是params参数必须是参数列表中的最后一个.但这是我了解指定默认值的参数.例:
MyMethod(string Name, int blah=0).
Run Code Online (Sandbox Code Playgroud)
所以问题是如果我需要在需要使用时指定上面的默认值params,可以这样做吗?如果是这样,必须在最后宣布?例:
MyMethod(int blah=0, params string[] variableData).
Run Code Online (Sandbox Code Playgroud)
再次感谢您的帮助.詹姆士
我正在尝试混合可选参数和可变长度参数(使用params关键字):
这是函数声明:
void foo(int req, string opt = "empty", params object[] rest) {}
Run Code Online (Sandbox Code Playgroud)
以下是对该函数的调用:
foo(1);
foo(1, "something");
foo(1, "something", 2, 3);
foo(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
最后一次调用不会编译,因为参数是在省略的可选参数之后提供的。(至少我认为这就是它不起作用的原因)
如何省略可选参数(opt)并仍然能够使用可变长度参数(rest)?
编辑:事实上,对C# 4.0,可选参数和参数不能一起工作的回答并不令我满意,因为在多个可选参数的情况下可能存在多种重载组合。
我有一个日志记录接口,我使用一些有用的扩展方法对其进行了扩展,以便我可以传递格式和参数列表,以避免每次调用该方法时都必须使用字符串格式。(它还帮助我遵循 FXCops 文化信息规则)
所以我可以打电话:
logger.Debug("Created {0} with id {1}",typeof(MyObject).Name ,myObject.Id);
Run Code Online (Sandbox Code Playgroud)
代替:
logger.Debug(string.Format("Created {0} with id {1}", typeof(MyObject).Name, myObject.Id));
Run Code Online (Sandbox Code Playgroud)
我现在发现自己处于一个有点棘手的情况,因为在日志中获取一些关于日志记录位置的信息(例如文件、方法和行号)会非常有帮助。这可能与整齐的实现[CallerMemberName],[CallerFilePath]和[CallerLineNumber]属性。
logger.Debug("Created {0} with id {1}", typeof(MyObject).Name, myObject.Id);
Run Code Online (Sandbox Code Playgroud)
然后会给我一个日志条目,例如:
“MyObjectProvider.cs,提供,第 50 行 | 创建的 MyObject,ID 为 1564”
这里的问题是方法签名看起来像这样:
public static void Debug(this ILogger logger, string format [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0, params object[] args)
Run Code Online (Sandbox Code Playgroud)
这是不可能的,因为[Caller*]属性使参数成为可选的,并且不适用于 args 参数。
我还尝试使用固定数量的字符串作为参数进行多个实现,如下所示:
public static void Debug(this ILogger logger, …Run Code Online (Sandbox Code Playgroud) 我有这个测试代码:
void func1(string a, params string[] p)
{
func1(a, true, p);
}
void func1(string a, bool b, params string[] p)
{
//...
}
void func2(string a, bool b = true, params string[] p)
{
//...
}
void exec()
{
func1("a", "p1", "p2");
func2("a", "p1", "p2");
}
Run Code Online (Sandbox Code Playgroud)
是func1和func2平等?
创建时没有错误func2,但是,当我尝试func2在exec中使用like时(使用可选值),编译器显示错误This function has some invalid arguments.
我认为func1并且func2对于将像API一样使用此功能的人来说是相同的.
这段代码有什么问题?我可以将此方法用于具有可选和params值的函数吗?
c# ×7
params ×3
function ×2
.net ×1
ambiguous ×1
args ×1
arguments ×1
java ×1
option-type ×1
overloading ×1
parameters ×1