Сообщение Ref Enumerable от 29.04.2021 5:39
Изменено 29.04.2021 20:07 VladD2
Ref Enumerable
Внезапно задумался, а почему не работает вот такое:
Ну, ладно, получаем CS1656, Cannot assign to 'd' because it is a 'foreach iteration variable'.
Ладно, всё верно, у нас там под капотом IEnumerable<int>, который возвращает IEnumerator<int>, у которого int Current{get;}. Действительно — куда там присваивать?
Но! У нас же есть возможность сделать ref int Current {get;}.
Жаль, но вот такой код компилироваться не будет:
В первой же строке у нас Unexpected token 'ref'.
Ладно, папенька, пойдём длинным путём.
[сs]
public interface IRefEnumerator<T>: IEnumerator, IDisposable
{
new ref T Current { get; }
}
public interface IRefEnumerable<T>
{
public IRefEnumerator<T> GetEnumerator();
}
public class ArrayEnumerable<T>: IRefEnumerable<T>
{
private T[] _data;
public ArrayEnumerable(T[] data ) => _data = data ?? throw new ArgumentNullException(nameof(data));
private class ArrayEnumerator<T>: IRefEnumerator<T>
{
private T[] _data;
private int _pos = -1;
public ArrayEnumerator(T[] data) => _data = data ?? throw new ArgumentNullException(nameof(data));
public ref T Current => ref _data[_pos];
object IEnumerator.Current => _data[_pos];
public void Dispose(){}
public bool MoveNext() => _pos++ < _data.Length;
public void Reset() => _pos = -1;
}
public IRefEnumerator<T> GetEnumerator() => new ArrayEnumerator<T>(_data);
}
public static class ArrayEnumerable
{
public static ArrayEnumerable<T> AsRefEnumerable<T>(this T[] data) => new ArrayEnumerable<T>(data);
}
[/cs]
Пока что всё компилируется.
Но вот почему
по-прежнему выдаёт CS1656? И можно ли это доработать, незначительно поправив Roslyn?
foreach(var k in new int[10])
k = 42;
Ну, ладно, получаем CS1656, Cannot assign to 'd' because it is a 'foreach iteration variable'.
Ладно, всё верно, у нас там под капотом IEnumerable<int>, который возвращает IEnumerator<int>, у которого int Current{get;}. Действительно — куда там присваивать?
Но! У нас же есть возможность сделать ref int Current {get;}.
Жаль, но вот такой код компилироваться не будет:
public static IEnumerable<ref T> RefEnumerable(this T[] data)
{
for (var i = 0; i < data.Length; i++)
yield return ref data[i];
}
В первой же строке у нас Unexpected token 'ref'.
Ладно, папенька, пойдём длинным путём.
[сs]
public interface IRefEnumerator<T>: IEnumerator, IDisposable
{
new ref T Current { get; }
}
public interface IRefEnumerable<T>
{
public IRefEnumerator<T> GetEnumerator();
}
public class ArrayEnumerable<T>: IRefEnumerable<T>
{
private T[] _data;
public ArrayEnumerable(T[] data ) => _data = data ?? throw new ArgumentNullException(nameof(data));
private class ArrayEnumerator<T>: IRefEnumerator<T>
{
private T[] _data;
private int _pos = -1;
public ArrayEnumerator(T[] data) => _data = data ?? throw new ArgumentNullException(nameof(data));
public ref T Current => ref _data[_pos];
object IEnumerator.Current => _data[_pos];
public void Dispose(){}
public bool MoveNext() => _pos++ < _data.Length;
public void Reset() => _pos = -1;
}
public IRefEnumerator<T> GetEnumerator() => new ArrayEnumerator<T>(_data);
}
public static class ArrayEnumerable
{
public static ArrayEnumerable<T> AsRefEnumerable<T>(this T[] data) => new ArrayEnumerable<T>(data);
}
[/cs]
Пока что всё компилируется.
Но вот почему
foreach(var k in (new int[10]).AsRefEnumerable())
k = 42;
по-прежнему выдаёт CS1656? И можно ли это доработать, незначительно поправив Roslyn?
Ref Enumerable
Внезапно задумался, а почему не работает вот такое:
Ну, ладно, получаем CS1656, Cannot assign to 'd' because it is a 'foreach iteration variable'.
Ладно, всё верно, у нас там под капотом IEnumerable<int>, который возвращает IEnumerator<int>, у которого int Current{get;}. Действительно — куда там присваивать?
Но! У нас же есть возможность сделать ref int Current {get;}.
Жаль, но вот такой код компилироваться не будет:
В первой же строке у нас Unexpected token 'ref'.
Ладно, папенька, пойдём длинным путём.
Пока что всё компилируется.
Но вот почему
по-прежнему выдаёт CS1656? И можно ли это доработать, незначительно поправив Roslyn?
foreach(var k in new int[10])
k = 42;
Ну, ладно, получаем CS1656, Cannot assign to 'd' because it is a 'foreach iteration variable'.
Ладно, всё верно, у нас там под капотом IEnumerable<int>, который возвращает IEnumerator<int>, у которого int Current{get;}. Действительно — куда там присваивать?
Но! У нас же есть возможность сделать ref int Current {get;}.
Жаль, но вот такой код компилироваться не будет:
public static IEnumerable<ref T> RefEnumerable(this T[] data)
{
for (var i = 0; i < data.Length; i++)
yield return ref data[i];
}
В первой же строке у нас Unexpected token 'ref'.
Ладно, папенька, пойдём длинным путём.
public interface IRefEnumerator<T>: IEnumerator, IDisposable
{
new ref T Current { get; }
}
public interface IRefEnumerable<T>
{
public IRefEnumerator<T> GetEnumerator();
}
public class ArrayEnumerable<T>: IRefEnumerable<T>
{
private T[] _data;
public ArrayEnumerable(T[] data ) => _data = data ?? throw new ArgumentNullException(nameof(data));
private class ArrayEnumerator<T>: IRefEnumerator<T>
{
private T[] _data;
private int _pos = -1;
public ArrayEnumerator(T[] data) => _data = data ?? throw new ArgumentNullException(nameof(data));
public ref T Current => ref _data[_pos];
object IEnumerator.Current => _data[_pos];
public void Dispose(){}
public bool MoveNext() => _pos++ < _data.Length;
public void Reset() => _pos = -1;
}
public IRefEnumerator<T> GetEnumerator() => new ArrayEnumerator<T>(_data);
}
public static class ArrayEnumerable
{
public static ArrayEnumerable<T> AsRefEnumerable<T>(this T[] data) => new ArrayEnumerable<T>(data);
}
Пока что всё компилируется.
Но вот почему
foreach(var k in (new int[10]).AsRefEnumerable())
k = 42;
по-прежнему выдаёт CS1656? И можно ли это доработать, незначительно поправив Roslyn?