简体   繁体   English

获取string []的out参数为IEnumerable <string>

[英]Getting an out parameter of string[] as IEnumerable<string>

Let's say we have a method: 假设我们有一个方法:

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

Is there a way to do something similar to this: 有没有办法做类似的事情:

IEnumerable<string> result;

SomeMethod(out result);

Edit: The point is, I dont' want to bind the out value to string[] , I'd like the code to work even if the method declaration is changed to SomeMethod(out List<string> outputValue) . 编辑:关键是,我不想将out值绑定到string[] ,即使方法声明更改为SomeMethod(out List<string> outputValue) ,我也希望代码能够工作。

It's not allowed to change the type of an out parameter because type safety cannot be guaranteed. 不允许更改out参数的类型,因为无法保证类型安全。 This is explained in detail in Eric Lippert's Blog . 这在Eric Lippert的博客中有详细解释。

Here is a code example how one could break type safety if it would be allowed: 这是一个代码示例,如果允许的话,如何打破类型安全:

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

Obviously this is only a problem if result is not in the same scope as the call to SomeMethod but the compiler will not check for that. 显然,如果结果与调用SomeMethod的范围不同,这只是一个问题,但编译器不会检查它。 It is just not allowed. 这是不允许的。

Change the method signature to public void SomeMethod(out IEnumerable<string> someStrings) . 将方法签名更改为public void SomeMethod(out IEnumerable<string> someStrings) You can assign a string[] to someStrings inside SomeMethod and if you later decide to use a List<string> you can assign that also without braking the call. 您可以将一个string[]分配给SomeMethod someStrings ,如果您以后决定使用List<string> ,也可以在不制动呼叫的情况下分配它。

Personally I would avoid out parameters in the first place: public string[] SomeMethod() . 我个人首先要避免输出参数: public string[] SomeMethod()

I'm sure it's not a best way, but you can write another method which do this job for you: 我确定这不是最好的方法,但你可以编写另一种方法来为你完成这项工作:

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

You can't do that and there is no way around that. 你不能这样做,没有办法解决这个问题。 One of the reasons why is that CLR doesn't support out , only ref . 其中一个原因是,CLR不支持out ,只能ref So out is actually represented as ref , with some special rules added by the C# compiler. 所以out实际上表示为ref ,C#编译器添加了一些特殊规则。

The simplest (and obvious) way around that is to create a separate variable: 最简单(也很明显)的方法是创建一个单独的变量:

string[] resultArray;

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

You could create a helper method to do that casting for you: 您可以创建一个帮助方法来为您执行该转换:

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

Usage: 用法:

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

But you would need a separate overload (and delegate type) for each number of parameters and the code doesn't actually look much better. 但是你需要为每个参数提供一个单独的重载(和委托类型),而且代码实际上看起来并没有那么好。 (The type parameters are necessary, type inference doesn't seem to work for this code.) (类型参数是必需的,类型推断似乎不适用于此代码。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM