Replies: 19 comments
-
/cc @VSadov |
Beta Was this translation helpful? Give feedback.
-
Also related: In case extending this to non-array types is desired, what's the advantage of translating |
Beta Was this translation helpful? Give feedback.
-
Both NOTE: the ref variables themselves in either case should not be re-bindable. I.E. cant do the difference between foreach(ref var item in array)
{
// fetches something from item without copying out the whole deal
var val = item.A.B.C;
// updates a part of item in-place
item.A.B.C = val + 1;
}
foreach(ref readonly var item in array)
{
// fetches something from item without copying out the whole deal
var val = item.A.B.C;
// ERROR: item is a readonly variable
// item.A.B.C = val + 1;
} There could be some subtleties around reference/generic arrays because of array covariance. In addition to arrays this can probably be generalized to some general ref indexing/iterating patterns. Interesting idea. |
Beta Was this translation helpful? Give feedback.
-
If we choose to support duck typing on ref indexers, perhaps we could also support it in non-ref case?
That was my intention by making it |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@alrz It's also more general, e.g. it could make sense to iterate And it's more consistent with the existing behavior of |
Beta Was this translation helpful? Give feedback.
-
Actually, I think if we are going to disallow |
Beta Was this translation helpful? Give feedback.
-
@svick I think it should not relate to indexer. |
Beta Was this translation helpful? Give feedback.
-
@alrz I propose
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
As I said
You should first understand that The point here is. What we really need is just let Such as public class RefList<T> : IRefEnumerable<T>
{
private T[] array;
private struct Iterator : IRefEnumerable<T>
{
int i;
RefList<T> refList;
public ref T Current { get => refList?.array?[i]; }
public bool MoveNext() { i++; return !(i >= refList?.array?.Length); }
}
public IRefEnumerator<T> GetEnumerator() => new Iterator(this);
}
var refList = new RefList<int>();
foreach(ref var i in refList)
i = 0; Whenever it foreach it then became // only one time interface casted. Could be solve with contravariant return type
var iter = refList.GetIterator();
while(iter.MoveNext())
{
ref var i = iter.Current;
i = 0;
} |
Beta Was this translation helpful? Give feedback.
-
Other BCL functions should be updated as well, e.g. 'Array.ForEach()' |
Beta Was this translation helpful? Give feedback.
-
@jnm2 fixed. thanks. |
Beta Was this translation helpful? Give feedback.
-
This discussion: #535 triggered an idea: use temporary Span over whole array-like types (arrays, List maybe all types implementing IList?) in order to be able to ref foreach on already existing types but dont implementing ref indexers or RefEnumerable. Spans implement internal GetRawPointer that return ref and propsed API surface suggest there should be ref indexer too which makes them perfect as a trick working over all existing types |
Beta Was this translation helpful? Give feedback.
-
@BreyerW What would modifying a Given foreach (int i in list)
{
list.Add(i * 2);
} This code currently throws an exception. foreach (ref int i in list)
{
list.Add(i * 2);
} This code would presumably also throw an exception, at least when implemented using foreach (ref int i in list.Span)
{
list.Add(i * 2);
} This code could not throw an exception. And if you tried to modify |
Beta Was this translation helpful? Give feedback.
-
@svick Good points, though i think list could still be modified as long as GC can track address on ref field of span (not sure though if GC is capable of such adv tracking). Even then there might be a hole when list become larger or smaller and there is no way to automatically update length of span (althought in this case just use length of array instead of span?). Well that was just an idea to support ref on existing types in case there wont be any RefEnumerator/ref indexer. |
Beta Was this translation helpful? Give feedback.
-
Note: |
Beta Was this translation helpful? Give feedback.
-
I also suggest to shorten |
Beta Was this translation helpful? Give feedback.
-
Moved from dotnet/roslyn#16155
->
Note: The iterator variable is not and can't be
ref
orref readonly
(a ref to something you can't write), i.e. we can't doitem = ref something
; but one should be able to explicitly make itreadonly ref readonly
(a ref that you can't reassign to something you can't write). By default, it'sreadonly ref
(a ref that you can't reassign) so that all restrictions on ref and iterator variables apply, e.g. they can't be captured or reassigned.Open question: can we allow this for other types via duck typing?
Rel: #38, #188
Beta Was this translation helpful? Give feedback.
All reactions