-1

Considering c# pointers and referencing with the following code

public class Content{
   public Content(){} //empty constructor
} //end of Content class, emptiest class ever

public class Variants{
  Content x;

  public Variants(){ //Variants constructor
    x = new Content(); //point x of this instance towards a Content object
  }
} //end of Variants class

void main(){
  Contents[] v = new Contents[1]; //array for storing a variable coming from a Variants object


   v[0] = ((Variants)new Variants()).x; //store x of the 
                                        //instance of Variants in our single cell.
   Print(typeof(v[0]))
}//end of main()

Is this a valid statement: v[0] = ((Variants)new Variants()).x; or it will leak objects?

and

Does v[0] point to the object referenced by x? In other words, when we say Print(typeof(v[0])), do we imediately jump to the object referenced by x or does it imply traveling from variants object to its x variable?

If computer indeed has to travel to variants instance then to x as we mention the 0th cell (due to the way the value was stored into array), will this Print be quicker:

    Variants temp = new Variants()
    Contents cTemp = temp.x; //reference variable to point directly at x

    v[0] = cTemp; //feed in this pointer, not Variants.x instruction

Print(typeof(v[0]))
  • C# doesn't leak objects. The closest you can get to a memory leak is to "pack-rat"; that is, to retain references to objects you no longer really need. As far as your question goes, it's not really clear what you're asking, but in C# as with other languages with pointers/references, a reference is a reference and always points to a specific object. Even if you got that reference from someplace else, there's no "memory" of that someplace else, you still are just referencing the object. – Peter Duniho Oct 18 '14 at 22:44
  • So the 0th cell of the array will point directly to the address of x and will not cause overhead through traveling by pointers because there won't be any need in them? Thank you, I can accept this as an answer if you put it forward –  Oct 18 '14 at 22:51
  • Yes, there's no "traveling by pointers". You got the reference to the object you wanted, and that reference always points directly to that object. (Lucas's answer looks fine to me, so I don't feel a need to add another :) ). – Peter Duniho Oct 18 '14 at 22:58
  • Thanks, this is really good news then :D –  Oct 18 '14 at 23:04

2 Answers2

0

Is this a valid statement: v[0] = ((Variants)new Variants()).x; or it will leak objects?

Yes, this is a valid statement, and it won't leak anything. This would be shorter though:

v[0] = (new Variants()).x;

Does v[0] point to the object referenced by x?

Yes, at that point, your Variants object may already have been garbage collected (or not, you don't know), as you don't keep any reference to it.

There's no such thing as object leak in C#. You can get a memory leak if you create a lot of reachable objects, for instance by adding objects to a static list and never removing them. But if any object becomes unreachable from other code, it will be garbage collected sooner or later.

Even if you have an object graph, like A points to B and B points to A, but no other reachable object points to either A or B, both of these objects will be collected.

Also, don't worry about the performance of this, an object dereference has really minimal impact.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
  • Note that "new Variants().x" is even shorter, and works just as well. :) – Peter Duniho Oct 18 '14 at 22:59
  • @Peter indeed, but I dislike it because of the quarter-second of confusion it causes every time I read it ;) – Lucas Trzesniewski Oct 18 '14 at 23:01
  • By the way, why will the object get collected, aren't we storing a reference to one of its variables? Will it keep the instance of Content though, referenced by x? –  Oct 18 '14 at 23:06
  • @AwkwardSilence This is called micro-optimization (I'd even say nano-optimization) at this point. I think you're getting it wrong. If you need more performance, you may want to double-check the data structures you're using first as this is what will make you gain or loose most of it. Are you iterating over an array instead of using a `HashSet` for instance? Maybe what you really need is a `Dictionary` at some point? Get the data structures right (1000 objects is *little*). Also, you can use a profiler to find the bottlenecks, they often hide in a place you wouldn't expect. – Lucas Trzesniewski Oct 18 '14 at 23:06
  • No, you're storing a reference to an object it also references. The "variable" x is irrelevant. That was just where the Variants object kept the reference, it's not the object itself. – Peter Duniho Oct 18 '14 at 23:07
  • @AwkwardSilence The `Contents` instance is not a part of the `Variants` instance. The `Variants` instance merely references a `Contents` instance, that's all. – Lucas Trzesniewski Oct 18 '14 at 23:08
  • 1
    To reiterate Lucas' point: first things first. You should at the moment focus on getting the code correct. If it turns out to be fast enough, you're done. If it's too slow then you can spend time looking into why, using the proper tools (like a profiler...definitely _not_ intuition and guessing). The question of storing one array of objects containing multiple values, or multiple arrays of individual values does come up, but only in very specialized scenarios. It's a waste to try to optimize for that scenario before you know you actually need to. – Peter Duniho Oct 18 '14 at 23:08
  • Most of our code is arrays by index + binary search and generic lists. Thank you for reminding of HashSet and Dictionary, we will consider them as well! –  Oct 18 '14 at 23:09
  • In most scenarios where you have many objects, binary search may prove much slower than proper structures using hash codes. I have two answers of mine on my mind that could be of interest to you: about [collection semantics](http://stackoverflow.com/a/26202545/3764814) and [equality comparers](http://stackoverflow.com/a/26202958/3764814). – Lucas Trzesniewski Oct 18 '14 at 23:14
0

The first statment won't leak anything. What it does is creating a variant which in turn will create a content, save the content and throw away variant, which at some other time will be garbage collected. No memory will be held indefinitely. BTW, why not create a content directly? Also, the cast in the line is unnecesary, as the new operator is already typed as variant, hence casting is redundant.

About Print(typeof(v[0])). First of all, I guess you're talking about Console.WriteLine right?. Then, the typeof call won't even compile. It expects a type, not a variable or an object reference as you're suppling. It can be typeof(Content) for a compile-time value or v[0].GetType() call for getting the type of a variable expression. Also, it won't return just a string as you seem to imply, but a whole Type object with complete information about the class.

And to the point of performance. I have my doubts about what is faster or slower. Going though the variant, it for sure needs 2 "hops" to reach the constant, but using the array also accesses the indexer of the Array class, which might also impose some overhead. Using a simple local variable is most likely to gain a few cycles, and in your sample code that's entirely possible. But to really answer the question of speed, a test and benchmark is needed. Everything else are just guesses, more or less educated but only guesses. The compiler may also optimize all those acceses making them equal after all. Also, consider that such differences, if any, will most likely to be minimal, and only noticeable and relevant if such code is called repeated in a tight loop.

I suppose that you have a C++ background, and trying to adapt that to C#. Most things are completely different (specially memory management and leaks). Both languages have almost nothing in common, save for the name and the syntax, but programming models are widely different.

Alejandro
  • 7,290
  • 4
  • 34
  • 59
  • Thank you! Yeah, profile is nice, just don't want to end up with something which is hard to re-write, for example recursion / stack form. Indeed, the final code has to be called 60 times per second by multiple creatures, it contributes to AI –  Oct 18 '14 at 23:16
  • Good point about the C++ background. If it's the case, you should treat C# references just like C++ pointers. (you can get real pointers in C# too but they serve a different purpose) – Lucas Trzesniewski Oct 18 '14 at 23:17