Re: Forevery() writable iterator mechanism in C# 3
- From: Shawnk <Shawnk@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Fri, 10 Mar 2006 09:47:27 -0800
Mike,
Imagine the same situation as in my reply to Jon Skeet with A_col[] and
B_col[].
The collection could be an int?[] array of nullable ints.
The '_itr_mth' LLP tag means 'Iterator Method'.
Problem assignment: Print out list of resident items with their identity
Code solution : Using 'out parameter' in an iterator method (one returning
Enumerable).
int l_actual_itm_idx = 0; // The actual int?[l_idx] non-null item index in
a sparse array of int?[100] items.
l_temp_itm_col_ins = m_source_itm_col_ins.
Actual_items_with_index_itr_mth( l_actual_itm_idx );
foreach( int l_int_emr in m_actual_item_int_based_gnc_col_ins )
{
System.Console.WriteLine("Item #{0} = {1}", l_actual_itm_idx,
l_int_emr );
}
If you work it out (and I didn't screw it up :-0) the output skips over
nullable 'slots' ia the terator method internals and only returns existing
items.
In addition it will set the l_actual_itm_idx (item index) to the index in
the int?[100]array which, in this contrived example, is the identity of the
item. (see response to Jon Skeet).
The temporary collection we generate (l_temp_itm_col_ins) acts as an
'iterative delegate' that can return the value of the item identity
(l_actual_itm_idx) along with the item.
Note that identity here, and this is key, is determined by the collection.
Although the 'identity' is contrived the key point is the collective
responsibility for determining datum l_actual_itm_idx. For collectively
determined pheonomea that exists 'in aggregate' the collection needs a 'data
channel' back to the iterative body (WriteLine).
Note, again key point, the item has no knowledge of its 'context state'
which is only internal to the collection and may, in fact, be dependent upon,
the sequence of iteration itself.
The traveling salesman problem and other 'path oriented solutions' can have
'weights' as sortable item properties and, therefore, expressed in a
mechanism similar to our contrived, but relevant, example.
I hope this answers your intitial question 'why would the inteface need
ref/out itself'
My next post will address transformative operations using sequencers.
Context is changeble, growing objects persisted in XML over a long period.
Key point. The data structure itself changes from one Item XML schema to
another.
This is schema composition (basically)
"Mike" wrote:
.
"shawnk" <Shawnk@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:B5D0BAE3-20A3-4F2C-9C14-0D4C4EE189FD@xxxxxxxxxxxxxxxx
I searched the net to see if other developers have been looking for a
writable iterator in C#. I found much discussion and thus this post.
Currently (C# 2) you can not pass ref and out arguments to an iterator
method (one returning IEnumerable). I WOULD like to do this for
transformative operations on a collection.
I realize the need to lock target, etc.
Does anyone know how to handle 'writable iterators' in C# 2?
Is anyone aware of feature requests for C# to provide a forevery() with a
matching interface like IEnumerable?
Thanks ahead of time. I want to put in a product feature request but want
to
do some research before hand.
Why would the interface need ref/out itself?
There's nothing stopping the "yield"ing function from destructively
modifying it's collection regardless of what it returns, is there? (Although
it's certainly not common or expected.)
A destructive operation will by definition be refelected in all references
to the collection, so "out" is not needed.
And if it's not destructive, you can just write a little "collect" wrapper
that'll go though the enum and return a new ICollection.
IMHO, if you are:
- making a copied list (non-destructive) or returning each element, then
use a return value
- if you are performing a destructive operation, make the fn "void" and
do not return a value - this make it clear what's going on
If all your types are reference types (class instances), then each returned
element from the enumerator is a shared, mutable, object - so you can always
change it through normal means. (This isn't C++, class instances aren't
passed by value on the stack) If you want to change the "stored" element
itself of the current iteration in the underlying collection from *outside*
of the enumertor function, that's another story -- but that's really bad
practice -- especially considering that there may be no actual underlying
collection at all - that's really a major point of "yield", to provide
referential transparency in such matters. Consider:
yield return 1;
yield return 2;
yield return 3;
Your not going to be able to "write" to this interator no matter what you
do.
One way to do this would be to expose an iterator that returned proxies for
the storage of each element, if in fact there is a backing-store for the
enumeration. For example:
// Of course, generics too...
interface IEnumStorageProxy { object Value { get; set; }};
interface IEnumHasStorage { GetStorageProxyEnum(); }
foreach ( object elem in coll)
elem.Change(blah); // changing object inside collection as usual
foreach ( IEnumStorageProxy cell in coll.GetStorageProxyEnum())
{
object oldVal = c.Value;
c.Value = new MyObject(); // replace the object in the collection
}
This requires no new language features, though the interfaces would need to
be exposed from the framework collections.
m
- References:
- Prev by Date: Re: c# CP210x Wrapper InteropServices IntPtr HandleRef problem
- Next by Date: Re: Effective strategy for using VSS in a development team?
- Previous by thread: Re: Forevery() writable iterator mechanism in C# 3
- Next by thread: Re: Forevery() writable iterator mechanism in C# 3
- Index(es):
Relevant Pages
|