4

假设我们有一个方法:

public void SomeMethod(out string[] someArray) { // ... }

有没有办法做类似的事情:

IEnumerable<string> result;

SomeMethod(out result);

编辑:重点是,我不想将输出值绑定到string[],即使方法声明更改为 ,我也希望代码能够工作SomeMethod(out List<string> outputValue)

4

3 回答 3

5

不允许更改 out 参数的类型,因为无法保证类型安全。这在Eric Lippert 的博客中有详细解释。

这是一个代码示例,如果允许的话,如何破坏类型安全:

IEnumerable<string> result;

public void Test()
{
   SomeMethod(out result);
}

public void SomeMethod(out string[] someArray)
{
   someArray = new string[];
   ChangeTheType();

   int n = someArray.Length;    // BANG!! - someArray is now a List<string>
}

public void ChangeTheType()
{
    result = new List<string>();
}

显然,如果结果与对 SomeMethod 的调用不在同一范围内,这只是一个问题,但编译器不会对此进行检查。这是不允许的。

将方法签名更改为public void SomeMethod(out IEnumerable<string> someStrings). 您可以将 a 分配string[]someStringsinside SomeMethod,如果您以后决定使用 a List<string>,您也可以在不中断呼叫的情况下分配它。

就我个人而言,我会首先避免使用 out 参数:public string[] SomeMethod().

于 2013-02-10T19:52:59.087 回答
2

我确定这不是最好的方法,但是您可以编写另一种方法来为您完成这项工作:

public class ClassA
    {
        private void SomeMethod(out IEnumerable<string> result)
        {
            string[] res;
            SomeMethod(out res);
            result = res;
        }

        public void SomeMethod(out string[] someArray)
        {
            someArray = new string[2];
        }

        void Test()
        {
            IEnumerable<string> result;
            SomeMethod(out result);
        }
    }
于 2013-02-10T17:24:50.627 回答
2

你不能这样做,也没有办法解决。原因之一是 CLR 不支持out,仅支持ref. Soout实际上表示为ref,并带有一些由 C# 编译器添加的特殊规则。

最简单(也是显而易见)的方法是创建一个单独的变量:

string[] resultArray;

SomeMethod(out resultArray);
IEnumerable<string> result = resultArray;

您可以创建一个辅助方法来为您执行该转换:

public delegate void ActionWithOut<T>(out T result);

public static void ConvertOut<TBase, TDerived>(
    ActionWithOut<TDerived> method, out TBase result)
    where TDerived : TBase
{
    TDerived derived;
    method(out derived);
    result = derived;
}

用法:

IEnumerable<string> result;
ConvertOut<IEnumerable<string>, string[]>(SomeMethod, out result);

但是对于每个数量的参数,您都需要一个单独的重载(和委托类型),并且代码实际上看起来并没有好多少。(类型参数是必需的,类型推断似乎不适用于此代码。)

于 2013-02-10T19:46:24.150 回答