|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
newbie question about data persistenceexplained in the doco ... at least that I can find. I do something in my code that works just fine, trouble is I don't know why. Here is is .. namespace WindowsApplication1 { public partial class Form1 : Form { static List<foo> foocollection; .. .. .. } private void Add_new_foo () { foo foonew =new foo(); foocollection.Add(foonew); } Now when I call Add_new_foo, it creates foonew and adds it to foocollection, as I want it to. However, as I understand it this is just an object reference to foonew in foocollection. But foonew only exists during Add_new_foo - its created on the stack. Why doesn't it disappear when we exit Add_new_foo, and cause the reference to foonew in foocollection to reference a deleted object? Is the garbage collector/compiler/something clever enough to know there is a reference to it in foocollection, and hence keep a persistent copy? As I say, the code works, and operates how I want it to, but I don't understand why. Can anybody help explain this to me? Assuming "foo" is a class (not a struct) the object/instance is a
reference-type and created on the heap, which is why it lives. The variable (pointer), however, is essentially a value-type and lives (in this case) on the stack, but we don't care about the variable itself if we have shared the reference with somebody. The first part of the following explains the difference: http://www.pobox.com/~skeet/csharp/parameters.html (the second part explains pass-by-value and pass-by-reference, which is a different concept often confused with this) Marc On 2007-11-23 22:59:03 -0800, "Peter Webb"
<webbfamily@DIESPAMDIEoptusnet.com.au> said: > Sorry about the stupid newbie questions, but some things aren't very You should look at the specific documentation on MSDN for the memory > well explained in the doco ... at least that I can find. management and garbage collection topics. I think they cover the basics pretty well. > [...] In addition to what Marc wrote, yes...the garbage collector is "clever > However, as I understand it this is just an object reference to foonew > in foocollection. But foonew only exists during Add_new_foo - its > created on the stack. Why doesn't it disappear when we exit > Add_new_foo, and cause the reference to foonew in foocollection to > reference a deleted object? Is the garbage collector/compiler/something > clever enough to know there is a reference to it in foocollection, and > hence keep a persistent copy? enough". It starts with "root" variables (statics and locals), but it's also aware of what a type contains. It doesn't just look at the first layer of data; it can follow the chain of references all the way down. So you've got a collection, and that collection contains a reference to the object you created. The GC can look at the collection and know that it contains that reference, and since the object is thus reachable, it won't be collected. Pete > Thanks. I have a related question, if that's OK. This one is really, really > So you've got a collection, and that collection contains a reference to > the object you created. The GC can look at the collection and know that > it contains that reference, and since the object is thus reachable, it > won't be collected. > > Pete > stupid. I use the List<> type extensively in my code, basically because I don't know how to make arrays "persistent". Certainly, I can make an array foo [] fooarray = new foo[10]; But the scope of this is only the method in which it is defined. My code (like everybody else's, I assume) has plenty of data that I want to keep in arrays that are accessible by many methods. Because I don't know how to do this, I have resorted to Static List<> types which I define inside Form1. I simply don't know how to construct a regular array foo[10] that has a scope wider than the method in which it was created. Sorry about this, but now having created my 20th or so List<> when all I really wanted a regular array - and having spent considerable time trying to work it out for myself - could somebody please put me out of my misery? Arrays and lists are both reference types, but actually I suspect
you're better off with a List<T> in this case (it will support Add etc). Declaring a long-lived array is usually just a case of declaring it as a field (instance or static) - I'll gloss over the subtleties, but if you currently have: class Program { // static List<T> field static List<Something> list = new List<Something>(); } then you can do the same with arrays (assuming you know the size) via: class Program { // static T-array field static Something[] array = new Something[10]; } If you post your current code somebody can probably explain in terms closer to your current situation... Finally - be very wary of too much use of static fields; you can run into trouble with both garbage-collection and thread-safety. Neither is fun. Marc Thankyou, thankyou, thankyou.
I should admit I am doing this just for fun, but I really appreciate the help. I have found this whole thing intensely interesting. I actually have post-grad in Computer Science, but object oriented programming wasn't on the syllabus 30 years ago. Now, 30 years later, there is a whole different paradigm for programming that I knew existed but never explored. I've probably now written about a 1,000 lines of C# code, but haven't used an array yet. So many things in an object model work better Lists and other data structures; a month ago I wouldn't have believed that you could write more than ten lines of code which does something useful without an array. I am so pleased I came across C# Express Edition. I originally just wanted to do some maths coding, and I asked in sci.math if anybody could recommend a programming environment for Windows, easy to install, and preferably with an IDE. I got a few recommendations for installing a Linux emulator and gcc, which I did, but boy was that cumbersome if you know nothing about Linux. Of the half dozen responses in sci.math, not one of them mentioned C# EE. I only heard about it when I asked a programmer at work. This would have to be the best free thing I have ever got. I must have said in presentations about a 100 times "Microsoft knows how to look after its developer community", and now I really believe it. I'm glad you have found C# rewarding.
> I originally just wanted to do some maths coding I can't believe I'm saying this, but if you are interested in mathwork, you might also want to have a quick look at F#; this is a .NET functional programming language similar to "OCaml". Personally I'm a C# advocate, but you may find it interesting. However, you'd struggle to find quite as much community support, as its target audience is smaller (unless you ask John Harrop ;-p). Not also that F# is still at current a research language (although productization by Microsoft has been formally anounced). Again; I'd stick with C#, but it is only fair to make an informed decision... Marc Peter Webb wrote:
Show quote > The scope of the *variable* is the method. The object itself doesn't have scope.>> >> So you've got a collection, and that collection contains a reference >> to the object you created. The GC can look at the collection and know >> that it contains that reference, and since the object is thus >> reachable, it won't be collected. >> >> Pete >> > > Thanks. I have a related question, if that's OK. This one is really, > really stupid. > > I use the List<> type extensively in my code, basically because I don't > know how to make arrays "persistent". > > Certainly, I can make an array > > foo [] fooarray = new foo[10]; > > But the scope of this is only the method in which it is defined. Assuming a class, as Marc Gravell pointed out, the object lives on the heap. It is not a variable, it does not have a lifetime bounded by that of pointers to it. The 'fooarray' variable is a pointer to the actual array, not the array itself. Just because one pointer goes out of scope doesn't mean that another pointer can't point to the same object. So the way to reach an object outside the scope of a particular block is to assign a reference to the object to a variable with a wider scope. -- Lew |
|||||||||||||||||||||||