Получение выходного параметра string[] в виде IEnumerable<string>
Допустим, у нас есть метод:
public void SomeMethod(out string[] someArray) { // ... }
Есть ли способ сделать что-то похожее на это:
IEnumerable<string> result;
SomeMethod(out result);
Изменить: Дело в том, что я не хочу связывать выходное значение с string[]
Я хотел бы, чтобы код работал, даже если объявление метода изменено на SomeMethod(out List<string> outputValue)
,
3 ответа
Нельзя изменять тип выходного параметра, потому что безопасность типов не может быть гарантирована. Это подробно объясняется в блоге Эрика Липперта.
Вот пример кода, как можно нарушить безопасность типов, если это будет разрешено:
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)
, Вы можете назначить string[]
в someStrings
внутри SomeMethod
и если позже вы решите использовать List<string>
Вы можете назначить это также без торможения вызова.
Лично я бы исключил параметры в первую очередь: public string[] SomeMethod()
,
Вы не можете сделать это, и нет никакого способа обойти это. Одна из причин, почему CLR не поддерживает out
, только ref
, Так out
на самом деле представляется как 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);
Но вам потребуется отдельная перегрузка (и тип делегата) для каждого количества параметров, и код на самом деле выглядит не намного лучше. (Параметры типа необходимы, вывод типа не работает для этого кода.)
Я уверен, что это не лучший способ, но вы можете написать другой метод, который сделает эту работу за вас:
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);
}
}