|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Iterating over a list and altering it?and I want to iterate over it, altering each string in the list. In C++, I'd just create an iterator and walk the list, so I was looking for something similar in C#. I looked at foreach, List.ForEach, and IEnumerator. The problem is that all of them seem to return readonly pointers to the items in the List. Therefore I can't alter the list. So I'm using a for loop, but ... I'm just baffled that there aren't any sort of iterators that let me alter the list. I have the feeling that there are, or that I'm just not using these right. So I figured I'd ask! Here's some of the code I tried ... note that udLine is a struct, and udList is a List of those structs. public List<udLine> udList = new List<udLine>(100); IEnumerator<udLine> enumerator = udList.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.header = enumerator.Current.header.PadLeft(LongestHeaderLength); } I really was curious to try this: public void AlterItem(udLine ud) { ud.header = ud.header.PadLeft(LongestHeaderLength); } and then call: udList.ForEach(AlterItem); but nothing happened. My guess was that the ud was getting copied, so I made it a ref argument: public void AlterItem(ref udLine ud) { ud.header = ud.header.PadLeft(LongestHeaderLength); } udList.ForEach(ref AlterItem); but the compiler really didn't like that. So I'm using a for loop. But is there a way to make either of the above statments work? Thank you! OK - you started talking strings, and ended with structs... I think
you need to clarify: are you a: trying to change the actual contents of the list (i.e. swap items with replacements), or b: update properties of items that are in the list? if "b" then a foreach loop is fine, but the problem here may be that you are using structures not classes; because these are value-typed they are going to get copied left right and centre. First rule: .Net structs should be immutable unless you really, really know what you are doing. That means that you have to switch to scenario "a". Now; for "a", note that changing the contents of the list (meaning: adding, removing, swapping, etc) breaks iterators. This is intentional. For this scenario the common solution is to use indexer syntax instead: for( int i = 0 ; i < list.count ; i++ ) { list[i] = theNewValuePerhapsFromTheOldValue(); } Hope this helps, Marc In addition to what Marc said, strings are _immutable_ reference type
in .NET so they behave like structs in terms of altering list elements -- you have to reassign the element in question, ergo you can't use iterators which are read-only with respect to the list. Sorry, Marc - I started with a simplified question for clarity and then
forgot my simplification. I have a list of structs. Most of the structs are strings, and I'm trying to alter one of the strings in each struct. It sounds like I ended up with the right answer in the end, with the for loop. I take it that the ForEach concept is more to get the data out and put it somewhere else than to operate on the data itself? Evan Reynolds wrote:
> Sorry, Marc - I started with a simplified question for clarity and then Just make it a class instead of a struct, and you can change the members > forgot my simplification. I have a list of structs. Most of the structs are > strings, and I'm trying to alter one of the strings in each struct. > > It sounds like I ended up with the right answer in the end, with the for > loop. I take it that the ForEach concept is more to get the data out and put > it somewhere else than to operate on the data itself? > of the class without problem.
Show quote
Hide quote
On Apr 5, 10:30 am, "Marc Gravell" <marc.grav***@gmail.com> wrote: I have to disagree that structs should be immutable in .NET - most of> OK - you started talking strings, and ended with structs... I think > you need to clarify: > > are you a: trying to change the actual contents of the list (i.e. swap > items with replacements), or b: update properties of items that are in > the list? > > if "b" then a foreach loop is fine, but the problem here may be that > you are using structures not classes; because these are value-typed > they are going to get copied left right and centre. First rule: .Net > structs should be immutable unless you really, really know what you > are doing. That means that you have to switch to scenario "a". > > Now; for "a", note that changing the contents of the list (meaning: > adding, removing, swapping, etc) breaks iterators. This is > intentional. For this scenario the common solution is to use indexer > syntax instead: > > for( int i = 0 ; i < list.count ; i++ ) { > list[i] = theNewValuePerhapsFromTheOldValue(); > > } > > Hope this helps, > > Marc the internal structs provided by .NET are not immutable... in fact, you'll find more classes are immutable than structs. In general, the approach is that, if you want a class that you can pass around to lots of objects, it should be immutable - that avoids the terrifying headache of aliasing (eg: fonts, strings, etc.). So really, you have it the other way around - if you want a class that will be used like a struct, make it immutable. Structs avoid aliasing automatically, since they're always copy. Personally, I think the important thing is to always KNOW that a struct is a struct - if you have to include the word "struct" in it's name, that's fine (since intellisense leaves out this freakishly crucial piece of information). Immutable structs defeat most of the advantages of using structs, and the compiler is sufficiently smart to catch most of the stupid crap you can get in trouble doing with a struct (IE changing values on a temporary that will be dropped). Besides, in most DotNet languages, immutables are a headache to implement (sixteen billion hand-coded constructors). Martin Z wrote:
> I have to disagree that structs should be immutable in .NET - most of I haven't made a count so I can't say that you are wrong, but I find > the internal structs provided by .NET are not immutable... in fact, > you'll find more classes are immutable than structs. that many of the most common structures are immutable, like for example Color, DateTime, Decimal and TimeSpan. All built-in basic types, like Int32 and Double, are of course also immutable. I know of only a few that actually are mutable, like Point, Size and Rect, and it has been widely debated if making them mutable was a good move or not. > In general, the Then I am not convinced that you are using structures the way that they > approach is that, if you want a class that you can pass around to lots > of objects, it should be immutable - that avoids the terrifying > headache of aliasing (eg: fonts, strings, etc.). So really, you have > it the other way around - if you want a class that will be used like a > struct, make it immutable. Structs avoid aliasing automatically, > since they're always copy. Personally, I think the important thing is > to always KNOW that a struct is a struct - if you have to include the > word "struct" in it's name, that's fine (since intellisense leaves out > this freakishly crucial piece of information). > > Immutable structs defeat most of the advantages of using structs, are intended. If you are using structures as if they were classes, then it would of course make no sense to make them immutable. On the other hand, in that case it doesn't really make sense to make them structures either. > and I rarely find that a structure would need more than a few constructors. > the compiler is sufficiently smart to catch most of the stupid crap > you can get in trouble doing with a struct (IE changing values on a > temporary that will be dropped). Besides, in most DotNet languages, > immutables are a headache to implement (sixteen billion hand-coded > constructors). With the limited size that is recommneded for structures, there can't be so many different ways of creating them. On Apr 5, 7:14 am, Evan Reynolds
<EvanReyno***@discussions.microsoft.com> wrote: Show quoteHide quote > I am a C++ programmer and have been learning C#. I have constructed a List<> Is there a particular reason why you chose to make udLine a struct> and I want to iterate over it, altering each string in the list. > > In C++, I'd just create an iterator and walk the list, so I was looking for > something similar in C#. I looked at foreach, List.ForEach, and IEnumerator. > The problem is that all of them seem to return readonly pointers to the > items in the List. Therefore I can't alter the list. So I'm using a for > loop, but ... I'm just baffled that there aren't any sort of iterators that > let me alter the list. I have the feeling that there are, or that I'm just > not using these right. So I figured I'd ask! > > Here's some of the code I tried ... note that udLine is a struct, and udList > is a List of those structs. > public List<udLine> udList = new List<udLine>(100); > > IEnumerator<udLine> enumerator = udList.GetEnumerator(); > while (enumerator.MoveNext()) > { > enumerator.Current.header = > enumerator.Current.header.PadLeft(LongestHeaderLength); > } > > I really was curious to try this: > public void AlterItem(udLine ud) > { > ud.header = ud.header.PadLeft(LongestHeaderLength); > } > > and then call: > udList.ForEach(AlterItem); > > but nothing happened. My guess was that the ud was getting copied, so I > made it a ref argument: > public void AlterItem(ref udLine ud) > { > ud.header = ud.header.PadLeft(LongestHeaderLength); > } > > udList.ForEach(ref AlterItem); > > but the compiler really didn't like that. > > So I'm using a for loop. But is there a way to make either of the above > statments work? rather than a class? Note that these two keywords have much more significant implications in C# than in C++. I suggest that you make udLine a class. Then there will be no need to pass it using "ref", and your problem should disppear.
Downloading unix \n text files, convert to \r\n non-unix?
Top posting how to listen a connection from a specific IP address? Reflection ok in 1.1, but not anymore in 2.0 Progress Bar refuses to work? RichText in asp.net IntelliSense Question. Thread problem with control delegate Forgot Syntax: calling a parameterized constructor of the same class from a non-parameterized one how to reassign a fixed pointer |
|||||||||||||||||||||||