1

The code is:

struct m1
{
    public int a;
    public int b;
}

int main()
{
    List <m1> mList;
    m1.initialize;
    //new. and add some items to it.

now I want to access the objects in mList at first I tried:

    for each(m1 it in mList)
    {
        m1.a = 5;
    }

but it failed. becuase after the for each I wrote m1.first().a on console. it was it's initialized value not 5.

then I tried

    for (int counter = 0; counter < mList.size(); counter++)
    {
        m1 it = mList[counter];
        it.a = 5;
    }

again the same problem.

then I tried

    for (int counter = 0; counter < mList.size(); counter++)
    {
        mList[counter].a = 5;
    }

it even didn't compiled. it gives me an error. it says something about not being modifiable return value of list.this[int].

then I tried

    for (int counter = 0; counter < mList.size(); counter++)
    {
        var m1 it = mList[counter];
        it.a = 5;
    }

it didn't work too. I tried all I could and everything that I found in internet and this site. Could you please help you to find a way to access parameters of objects(of type struct) in list? Obviously it is easy when list is made from objects(from classes). it comes to complication if I want to made a list from objects of structs. Any help would highly welcomed.

Masoud
  • 1,354
  • 6
  • 18
  • 30
  • console.writeline(mlist.First().a) – Masoud Aug 26 '12 at 08:38
  • for sure there should be a way. it couldn't be completely impossible. it means that I can't access to objects in list??? – Masoud Aug 26 '12 at 08:40
  • @Masoud: My suspicion is that you don't understand how value types work. You don't have "objects" at all - you have values of a value type. – Jon Skeet Aug 26 '12 at 08:42

3 Answers3

10

The problem is that you've put a struct in a list. When you fetch it from the list, that will create a copy - so modifying it won't do any good. Given your comments, it's possible that you're confused about how value types and reference types work in C#, in which case I suggest you read my article on the topic (or books, or MSDN etc).

You'd need to fetch it, modify the copy, then replace the value in the list:

var copy = list[index];
copy.a = 5;
list[index] = copy;

However, I would strongly advise against creating mutable value types in the first place, partly because they cause exactly this sort of problem. Value types should usually be used for more "fundamental" values which can't be changed in place. It doesn't make sense to change what "the number 5" means, for example, or "January 1st at 10am". If you change the meaning, you've got a new value - so force that to genuinely be a new value.

It's unclear (due to lack of context) whether you should be creating an immutable value type and replacing it in the list, or creating a mutable reference type (a class) instead. Or possibly even an immutable reference type, as that can often aid readability.

I'd also advise against using public fields - use properties instead, to separate implementation details from the type's API.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • isn't anyway of avoiding these copy works? speed is very very important in my program. – Masoud Aug 26 '12 at 08:42
  • 1
    @Masoud: I suggest you understand how the language works before you start trying to micro-optimize. – Jon Skeet Aug 26 '12 at 08:44
  • I used structs because I should keep million objects of a special type in memory. and if I create them as class objects their too space consuming. I need a very compact type. – Masoud Aug 26 '12 at 08:46
  • @Masoud: A million objects really isn't that many. But again - get something working in the most natural, elegant, readable way first, then measure performance, *then* optimize if necessary. – Jon Skeet Aug 26 '12 at 08:48
  • I get what you said. I used to code in c++. it was really easier to handle such things with great power of pointers and other things but as I said I need to keep lots of objects in memory and class objects are very big for this work so I tired to use structs instead of them. is there any thing that I missed? – Masoud Aug 26 '12 at 08:48
  • yes. 50 million object is. because if object is in size of 100 bytes. it is 5 gigabyte. but if I use struct it is about 4 bytes and it is 200megabytes. so it is really a big difference. sometimes efficiency is a lot more important than readability. and my program is really one of 'em. – Masoud Aug 26 '12 at 08:51
  • @Masoud: Um, why would a reference type be 100 bytes if a struct is 4 bytes? The object overhead really *isn't* 96 bytes. And until you've got *working code*, you can't tell whether the readable code is going to perform well enough or not. It seems that you're making incorrect assumptions ("class objects are very big") to start with. Maybe you *should* use structs - but in that case I'd still make them immutable, and you'll absolutely have to copy them back if you use a `List`. You wouldn't with an array, but that has other limitations. – Jon Skeet Aug 26 '12 at 08:59
  • It sounds like you're going to ignore my advice anyway though, so I'll stop at this point. – Jon Skeet Aug 26 '12 at 08:59
  • No. I didn't want to ignore your advice. But this program should at least do for example 50Milion object check in a minute or it is completely useless. so speed is what the program's mean is. – Masoud Aug 26 '12 at 09:03
  • I checked the difference in sizes. it is even more than this. – Masoud Aug 26 '12 at 09:05
  • @Masoud: "I checked the difference in sizes. it is even more than this." Then your diagnostics are incorrect. See http://msmvps.com/blogs/jon_skeet/archive/2011/04/05/of-memory-and-strings.aspx for more details. And yes, you really *are* ignoring my advice. You're *assuming* that you know that the code will perform too badly if you write it in a more readable form. You have *definitely incorrect* figures (your struct would take 8 bytes anyway as it contains 2 4-byte integers, and as a class it would take 16 or 24 bytes per instance depending on whether you're using a 32 or 64-bit CLR). – Jon Skeet Aug 26 '12 at 09:10
2

Try this:

m1 temp ;
for (int counter = 0; counter < mList.size(); counter++)
    {
        temp = mList[counter];
        temp.a = 5;
        mList[counter] = temp
    }
Embedd_0913
  • 16,125
  • 37
  • 97
  • 135
1

if you are interesting to work with struct without using a temporary variable: use a struct collection:

           m1[] mList = new m1[100];
            //initialize 100 items

            for (int i = 0; i < 100; i++)
            {
                mList[i].a = 5;
            }
Hassan Boutougha
  • 3,871
  • 1
  • 17
  • 17