C#4.0可选的out / ref参数

时间:2010-05-20 01:45:50

标签: c#-4.0 optional-parameters optional-arguments

C#4.0是否允许可选的outref参数?

9 个答案:

答案 0 :(得分:178)

没有

解决方法是使用具有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指出这一点。)

答案 1 :(得分:86)

正如已经提到的,这是不允许的,我认为这是非常有意义的。 但是,要添加更多详细信息,请参阅C# 4.0 Specification第21.1节中的引用:

  

构造函数,方法,索引器和委托类型的形式参数可以声明为可选:

     

固定参数:
   attributes opt parameter-modifier opt type identifier default-argument opt
  默认参数:
   =表达

     
      
  • 带有默认参数固定参数可选参数,而固定参数没有默认参数必需参数
  •   
  • formal-parameter-list 中的可选参数后,无法显示必需参数。
  •   
  • refout参数不能包含默认参数
  •   

答案 2 :(得分:61)

不,但另一个很好的选择是让方法使用通用模板类作为可选参数,如下所示:

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

答案 3 :(得分:26)

实际上有一种方法可以做到这一点,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.

为了使其编译,您需要在项目选项中启用不安全的代码。这是一个通常不应该使用的真正hacky解决方案,但是如果你做一些奇怪的,神秘的,神秘的,管理启发的决定,真的需要在C#中选择out参数,那么这将允许你这样做

答案 4 :(得分:5)

ICYMI:包含在C#7.0枚举here的新功能中,“丢弃”现在允许作为_形式的输出参数,让您忽略不关心的参数:< / p>

p.GetCoordinates(out var x, out _); // I only care about x

P.S。如果您还对“out var x”部分感到困惑,请阅读链接上有关“Out Variables”的新功能。

答案 5 :(得分:1)

不,但您可以使用代理人(例如Action)作为替代方案。

在面对我认为我想要一个可选输出参数的情况时,部分由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

它不适合所有用例,但适用于我的实际用例(为单元测试提供数据的函数,以及新单元测试需要访问返回值中不存在的某个内部状态的函数)。

答案 6 :(得分:0)

对于C#6.0及更低版本,请使用没有out参数的重载方法来调用带有out参数的方法。我不确定为什么当专门询问C#4.0是否可以具有可选的out参数时,为什么.NET Core的C#7.0甚至是此线程的正确答案。答案是否定的!

答案 7 :(得分:-2)

这样怎么样?

public bool OptionalOutParamMethod([Optional] ref string pOutParam)
{
    return true;
}

您仍然必须将值传递给C#中的参数,但它是一个可选的参数参数。

答案 8 :(得分:-4)

expand_aliases