C#4.0是否允许可选out
或ref
参数?
null
默认值(我来自PHP)并进行测试null
以继续填充参数(对于那些熟悉的人,preg_match()
我认为),我已经相当习惯于通过引用来引用可选参数,尽管从技术角度来看,这目前可能是不可能,而且PHP和C#不可比,它仍然是可用的“ 不错 ”的工具。
C#4.0是否允许可选out
或ref
参数?
null
默认值(我来自PHP)并进行测试null
以继续填充参数(对于那些熟悉的人,preg_match()
我认为),我已经相当习惯于通过引用来引用可选参数,尽管从技术角度来看,这目前可能是不可能,而且PHP和C#不可比,它仍然是可用的“ 不错 ”的工具。
Answers:
如前所述,这是完全不允许的,我认为这非常有意义。但是,要添加更多详细信息,以下是C#4.0规范 21.1节的引文:
构造函数,方法,索引器和委托类型的形式参数可以声明为可选:
固定参数:
属性opt参数修饰符opt类型标识符default-argument opt
default-argument:
=表达式
- 甲固定参数用默认参数的是一个可选参数,而一个固定参数没有缺省参数的是一个必需的参数。
- 必需参数不能出现在formal-parameter-list中的可选参数之后。
- 一个
ref
或out
参数不能有默认参数。
没有。
一种解决方法是使用另一个没有 out / ref参数的方法重载,该方法仅调用您的当前方法。
public bool SomeMethod(out string input)
{
...
}
// new overload
public bool SomeMethod()
{
string temp;
return SomeMethod(out temp);
}
更新:如果您具有C#7.0,则可以简化:
// new overload
public bool SomeMethod()
{
return SomeMethod(out _); // declare out as an inline discard variable
}
(感谢@Oskar / @Reiner指出这一点。)
return SomeMethod(out string temp)
。在此处查看更多信息:blogs.msdn.microsoft.com/dotnet/2016/08/24/…–
return SomeMethod(out _);
不,但是另一种替代方法是让该方法对可选参数使用通用模板类,如下所示:
public class OptionalOut<Type>
{
public Type Result { get; set; }
}
然后,您可以按以下方式使用它:
public string foo(string value, OptionalOut<int> outResult = null)
{
// .. do something
if (outResult != null) {
outResult.Result = 100;
}
return value;
}
public void bar ()
{
string str = "bar";
string result;
OptionalOut<int> optional = new OptionalOut<int> ();
// example: call without the optional out parameter
result = foo (str);
Console.WriteLine ("Output was {0} with no optional value used", result);
// example: call it with optional parameter
result = foo (str, optional);
Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result);
// example: call it with named optional parameter
foo (str, outResult: optional);
Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result);
}
实际上,C#允许使用一种方法来执行此操作。这回到C ++,而违反了C#的漂亮的面向对象结构。
谨慎使用该方法!
这是使用可选参数声明和编写函数的方式:
unsafe public void OptionalOutParameter(int* pOutParam = null)
{
int lInteger = 5;
// If the parameter is NULL, the caller doesn't care about this value.
if (pOutParam != null)
{
// If it isn't null, the caller has provided the address of an integer.
*pOutParam = lInteger; // Dereference the pointer and assign the return value.
}
}
然后像下面这样调用函数:
unsafe { OptionalOutParameter(); } // does nothing
int MyInteger = 0;
unsafe { OptionalOutParameter(&MyInteger); } // pass in the address of MyInteger.
为了进行编译,您需要在项目选项中启用不安全的代码。这是一个非常棘手的解决方案,通常不应该使用,但是如果您要做出一些奇怪,神秘,神秘,受管理启发的决定,则确实需要C#中的可选out参数,那么您就可以做到这一点。
ICYMI:此处列举的C#7.0的新功能中包括“丢弃”,现在允许以_的形式作为out参数,以让您忽略不需要的参数:
p.GetCoordinates(out var x, out _); // I only care about x
PS,如果您也对“ out var x”部分感到困惑,请阅读链接上有关“ Out Variables”的新功能。
不,但是您可以使用委托(例如Action
)作为替代。
在遇到我以为我想要可选的out参数的情况时,部分受Robin R的回答启发,我改用了Action
委托。我借用了他的示例代码进行修改以使用,Action<int>
以显示差异和相似之处:
public string foo(string value, Action<int> outResult = null)
{
// .. do something
outResult?.Invoke(100);
return value;
}
public void bar ()
{
string str = "bar";
string result;
int optional = 0;
// example: call without the optional out parameter
result = foo (str);
Console.WriteLine ("Output was {0} with no optional value used", result);
// example: call it with optional parameter
result = foo (str, x => optional = x);
Console.WriteLine ("Output was {0} with optional value of {1}", result, optional);
// example: call it with named optional parameter
foo (str, outResult: x => optional = x);
Console.WriteLine ("Output was {0} with optional value of {1}", result, optional);
}
这样做的好处是,可选变量在源中显示为普通int(编译器将其包装在闭包类中,而不是我们将其显式包装在用户定义的类中)。
该变量需要显式初始化,因为编译器无法假定Action
在函数调用退出之前将调用。
它并不适合所有用例,但对于我的实际用例(用于为单元测试提供数据的功能,以及其中新的单元测试需要访问返回值中不存在的某些内部状态的功能)工作得很好。
这样子怎么办
public bool OptionalOutParamMethod([Optional] ref string pOutParam)
{
return true;
}
您仍然必须将值从C#传递给参数,但这是可选的ref参数。
[Optional]
注释。这无济于事。
void foo(ref int? n)
{
return null;
}