Почему методы итератора не могут принимать параметры ref или out?
Если вы хотите вернуть итератор parameter и int из вашего метода, обходной params путь:
public class Bar : IFoo
{
public IEnumerable GetItems( ref int somethingElse )
{
somethingElse = 42;
return GetItemsCore();
}
private IEnumerable GetItemsCore();
{
yield return 7;
}
}
Следует отметить, что c-sharp ни один код внутри метода ref итератора (т.е. в основном parameters метод, содержащий yield return
или yield break
) не c-sharp выполняется до тех пор, пока .cs-file не будет вызван метод MoveNext()
в .cs-file перечислителе. Итак, если csharp бы вы могли использовать c# out
или ref
в своем методе итератора, вы params бы получили такое удивительное out поведение:
// This will not compile:
public IEnumerable GetItems( ref int somethingElse )
{
somethingElse = 42;
yield return 7;
}
// ...
int somethingElse = 0;
IEnumerable items = GetItems( ref somethingElse );
// at this point somethingElse would still be 0
items.GetEnumerator().MoveNext();
// but now the assignment would be executed and somethingElse would be 42
Это распространенная visual-c# ошибка, связанная с этим .cs-file проблема:
public IEnumerable GetItems( object mayNotBeNull ){
if( mayNotBeNull == null )
throw new NullPointerException();
yield return 7;
}
// ...
IEnumerable items = GetItems( null ); // <- This does not throw
items.GetEnumerators().MoveNext(); // <- But this does
Таким образом, хороший visual-c# шаблон - разделить методы params итератора на две части: одну ref для немедленного выполнения c#.net и другую, содержащую код, который c#-language должен выполняться лениво.
public IEnumerable GetItems( object mayNotBeNull ){
if( mayNotBeNull == null )
throw new NullPointerException();
// other quick checks
return GetItemsCore( mayNotBeNull );
}
private IEnumerable GetItemsCore( object mayNotBeNull ){
SlowRunningMethod();
CallToDatabase();
// etc
yield return 7;
}
// ...
IEnumerable items = GetItems( null ); // <- Now this will throw
ИЗМЕНИТЬ:
Если params вам действительно нужно поведение, при c#-language котором перемещение итератора c-sharp изменяет параметр ref
, вы можете parameter сделать что-то вроде этого:
public static IEnumerable GetItems( Action setter, Func getter )
{
setter(42);
yield return 7;
}
//...
int local = 0;
IEnumerable items = GetItems((x)=>{local = x;}, ()=>local);
Console.WriteLine(local); // 0
items.GetEnumerator().MoveNext();
Console.WriteLine(local); // 42
c#
parameters
ref
out
Почему методы итератора не могут принимать параметры ref или out?
Мы используем файлы cookies для улучшения работы сайта. Оставаясь на нашем сайте, вы соглашаетесь с условиями использования файлов cookies. Чтобы ознакомиться с нашими Положениями о конфиденциальности и об использовании файлов cookie, нажмите здесь.