c# 4.0允许可选的out或ref参数吗?


当前回答

不,但你可以使用委托(例如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将在函数调用退出之前被调用。

它并不适合所有的用例,但是对于我的实际用例(一个为单元测试提供数据的函数,并且一个新的单元测试需要访问一些没有在返回值中出现的内部状态)来说效果很好。

其他回答

ICYMI:包括在这里列举的c# 7.0的新特性中,“discards”现在被允许以_的形式作为out参数,让你忽略你不关心的out参数:

p.GetCoordinates(out var x, out _);//我只关心x

附注:如果你也对“输出变量x”的部分感到困惑,请阅读链接上关于“输出变量”的新功能。

void foo(ref int? n)
{
    return null;
}

对于c# 6.0及以下版本,使用不带out形参的重载方法调用带out形参的方法。当被特别问到c# 4.0是否可以有一个可选的out参数时,我不确定为什么用于。net Core的c# 7.0甚至是这个线程的正确答案。答案是否定的!

不,但你可以使用委托(例如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将在函数调用退出之前被调用。

它并不适合所有的用例,但是对于我的实际用例(一个为单元测试提供数据的函数,并且一个新的单元测试需要访问一些没有在返回值中出现的内部状态)来说效果很好。

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

为了进行编译,您需要在项目选项中启用不安全代码。这是一个通常不应该使用的解决方案,但如果你为了一些奇怪的,神秘的,管理灵感的决定,确实需要一个可选的out参数在c#中,那么这将允许你这样做。