Si desea volver a la vez un repetidor y un int de su método, una solución es la siguiente:
public class Bar : IFoo
{
public IEnumerable<int> GetItems(ref int somethingElse)
{
somethingElse = 42;
return GetItemsCore();
}
private IEnumerable<int> GetItemsCore();
{
yield return 7;
}
}
Debe tener en cuenta que ninguna de código dentro de una el método del iterador (es decir, básicamente un método que contiene yield return
o yield break
) se ejecuta hasta que se llame al método MoveNext()
en el Enumerator. Así que si usted fuera capaz de utilizar out
o ref
en su método iterador, se llega a un comportamiento sorprendente de esta manera:
// This will not compile:
public IEnumerable<int> GetItems(ref int somethingElse)
{
somethingElse = 42;
yield return 7;
}
// ...
int somethingElse = 0;
IEnumerable<int> 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
Este es un error común, un tema relacionado es la siguiente:
public IEnumerable<int> GetItems(object mayNotBeNull){
if(mayNotBeNull == null)
throw new NullPointerException();
yield return 7;
}
// ...
IEnumerable<int> items = GetItems(null); // <- This does not throw
items.GetEnumerators().MoveNext(); // <- But this does
por lo Un buen patrón es separar los métodos del iterador en dos partes: una para ejecutar inmediatamente y otra que contiene el código que debe ejecutarse de forma perezosa.
public IEnumerable<int> GetItems(object mayNotBeNull){
if(mayNotBeNull == null)
throw new NullPointerException();
// other quick checks
return GetItemsCore(mayNotBeNull);
}
private IEnumerable<int> GetItemsCore(object mayNotBeNull){
SlowRunningMethod();
CallToDatabase();
// etc
yield return 7;
}
// ...
IEnumerable<int> items = GetItems(null); // <- Now this will throw
EDIT: Si realmente desea el comportamiento cuando se mueve el iterador modificaría la -parámetro ref
, se podría hacer algo como esto:
public static IEnumerable<int> GetItems(Action<int> setter, Func<int> getter)
{
setter(42);
yield return 7;
}
//...
int local = 0;
IEnumerable<int> items = GetItems((x)=>{local = x;},()=>local);
Console.WriteLine(local); // 0
items.GetEnumerator().MoveNext();
Console.WriteLine(local); // 42
¿Ocurrió algo cuando intentaste esto o nos pides tu razón para probarlo? –
Discuto algunas de estas consideraciones de diseño aquí: http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx –
solución moderna : http://answers.unity3d.com/answers/551381/view.html – Fattie