Jump to content
Xtreme .Net Talk

Leaderboard

Popular Content

Showing content with the highest reputation on 11/26/09 in all areas

  1. I've seen certain questions asked a number of times and decided that it would be appropriate to have some reference that clearly explains the details of this tricky aspect of function calls. To get the most out of this you should understand the concept of pointers and the difference between value-type objects and reference-type objects. Pointers, Pointers Everywhere Like traditional VB, DotNet languages (C++ aside, this article will focus on VB and C#) do an excellent job of hiding pointers from the programer, despite the fact that they are a very fundamental aspect of DotNet programming, used with reference types, pass-by-reference parameters, Delegate objects, and unsafe C# code. In order to understand the intricacies involved in all of these aspects of programming, however, the programmer must be aware of how pointers play into DotNet programming. Reference types Ultimately, references are dumbed down pointers. Of course, this is not an insult at our programming ability, but it is necessitated by our programming paradigm. DotNet is intended to be a purely object-oriented programming language, and memory addresses, dereferencing, and pointer math don't fit the bill. The downside, however, is that it is easy to forget (and just as easy to never realize in the first place) that we are using pointers. A variable that holds a reference to a DotNet object actually simply holds a pointer to that object. A reference is a pointer. See Figure 1, which pictures a value type variable, which directly holds data, and a reference type variable, which holds a pointer to data. Handles Okay, I lied. DotNet references aren't pointers. They are handles. So, what is the difference? In general, the difference between a pointer and a handle is that a pointer contains an actual memory address, whereas a handle contains a value which identifies a resource. This value may be a pointer. It may not. (In fact, you could think of a pointer as a type of handle.) The point is that the term "handle" stipulates certain behavior (a subset of the features and behavior of a pointer). Handles are usually some kind of pointer, quite often a pointer to a pointer, though they can be as simple as the index of an object in a list of objects. But DotNet handles are actually pointers to runtime data for our DotNet objects (which is actually stapled onto the beginning of our objects in memory), so for the sake of this discussion the statement that DotNet references are pointers is sufficiently accurate. Pass-By-Reference Arguments Arguments are passed to functions on the stack. When you pass an argument to a function by reference (using the ref or out keywords in C# or the ByRef keyword in VB) a pointer to the argument is placed on the stack instead of the object itself. This behavior allows us to prevent large objects from having to be copied to the stack and allows the function being called to write back to the original variable. The Confusion The question I see all too often is whether or not there is any difference between passing a reference object by reference versus passing a reference object by value. Either way you are passing a pointer, right? So there is no difference, right? And, of course, we would not be right. Let is investigate some different scenarios involving reference types, value types, and by-reference and by-value arguments. Of course, DotNet does a great job simplifying things, so all of these scenarios would look very similar when written in code, but the resulting compiled code would look pretty different (and it very well could behave equally differently). Value-Type Pass-By-Value This is a very simple and relatively common way of passing arguments to a function. This is how one usually passes an integer, a Rectangle, an enumeration, or any other value type object. The object itself is copied onto the stack. It may be examined by the callee (the function that is being called), but the original object can not be modified because the object passed to the callee is a copy and changes will not be reflected in the original. See Figure 2a. Value-Type Pass-By-Reference This is a much less common way to pass arguments to a function. Any time you see the word "reference," think pointer. Instead of copying the object onto the stack, a pointer is placed on the stack which points to the original object. This means two things. Firstly, the callee has direct access to the original object via the pointer and may freely modify its value. Secondly, large objects will not need to be copied, which may improve performance (though you would need to see a huge number of function calls with large numbers of large objects in order for this to be truly advantageous). See Figure 2b. Note that the original data can be accessed via the pointer on the stack. Reference-Type Pass-By-Value This is another common way to pass arguments to a function. Since we are using a reference-type object, we will place a reference on the stack. And what is a reference? A pointer! So we will be placing a pointer to an object on the stack. Say, does that sound familiar? It does! That is exactly what we did when we passed a value-type object by reference. There is an important difference though. There are certain restrictions imposed upon us with reference-type objects that aren't there with value-type objects. For instance, would could copy the data from one Rectangle object directly to another Rectangle object. We don't have this kind of direct access, however, with reference-type objects. Not because it is not possible, but because DotNet doesn't allow it. We can only access reference-type objects via public properties and methods. If it weren't for these restrictions, reference-type passed by-value would be exactly the same as value-type passed by-reference. See Figure 2c. Note that the end result on the stack is essentially identical to that of figure 2b. Reference-Type Pass-By-Reference This exceedingly rare creature is the most confusing of them all. See that we have the word "reference" in there twice? Two references means two pointers. Or to be more specific, a pointer to a pointer. The fact that we have a pointer to a pointer means that the callee (the function being called) has direct access to the reference that was passed into the function. In other words, the callee can change the reference and cause it to point to something else. No other argument marshalling mechanism provides this (rarely useful) capability. You can pass a Form to a function, and after the function is called, your variable that referenced said form could, for all you know, reference a completely different form. This, however, is the only difference between reference by-value and reference by-reference. See Figure 2d. Note that the stack contains a pointer to a pointer, allowing us to modify what that pointer points to. In And Out C# offers a parameter marshalling scenario in addition to the default pass-by-value mechanism and the pass-by-reference mechanism (using the ref keyword). Although it isn't essential to understanding the difference between by-value and by-reference mechanisms, it is related and I will cover it anyways to complete the article. C# allows parameters to use the out modifier as an alternative to the ref modifier (or no modifier at all). The out modifier specifies that a variable is passed-by-reference (i.e. a pointer is placed on the stack), but stipulates that the variable isn't necessarily initialized when it is passed into a function, and that the variable must be initialized before the function is finished. The purpose is to provide a mechanism that allows a function to return more than one value. Although this would be possible to do with a ref parameter, using an out parameter forces the function being called to return a value through the parameter. From within the function being called it would be an compiler error to not return something through an out parameter, and it would be a compiler error to read the value of the out parameter before assigning to it.
    1 point
  2. This is just an overview of what a good DotNet programmer should know about garbage collection and disposable objects, prompted by this post. Garbage Collection There are plenty of thorough articles about garbage collection, so I will only quickly cover the basics. All class objects, or "reference type" objects, are tracked by the garbage collector. At certain points that the garbage collector deems safe, execution of a program is halted and the garbage collector identifies which objects are reachable and which objects aren't. This is done by starting at certain "roots" and tracing references to see which objects are still connected to the program one way or another. These roots include static ("shared" in VB) variables, call stacks for all threads, unmanaged callbacks, and more. The garbage collector also uses a generation system. When an object is created it is first generation. Each time a collection occurs, all objects that are checked but not collected move to the next generation (stopping at the third generation). Most garbage collections only check first generation objects, fewer check second generation objects, and fewer yet check third generation objects. This way, objects that are used for longer periods of time are checked less frequently. Disposable Objects The IDisposable interface exists primarily to allow you to explicitly release unmanaged resources (close files and connections and free Windows resources). You should implement this interface in the following scenarios: When you directly acquire unmanaged resources (you will most likely be using some sort of interop in this case, such as COM or P/invoke) When your object retains other disposable objects When there is important finalization for your object that should be done as soon as possible. All IDisposable objects should be disposed when you are done with them. That means that you will need to keep a reference to the object one way or another until you call Dispose. And just because you dispose an object doesn't mean that the garbage collector is done with it, so you should also release your reference to the object after you dispose it. To Handle The GC Or Not To? That is the question. Almost always, it is best to let the garbage collector do its own thing. (That is the answer.) The two reasons for this are, firstly, that the garbage collector is there so you don't have to worry about managing memory, and secondly, that it does it's job well. So when should you explicitly invoke GC.Collect and force a garbage collection? You should do this when you are incredibly familiar with the garbage collection system, have decided that this will improve garbage collection performance, and are willing to perform thorough tests to confirm that you are indeed making an improvement by stepping in and bossing the garbage collector around. If you are really interested in optimizing garbage collection here are some tips. When you are done with an object, set the reference to null to "disconnect" the object from your program and allow it to be collected (if the variable will go out of scope it isn't necessary to clear the reference, as long is it disappears one way or another). Don't cache objects unless it is very expensive to instantiate them. For smaller or simpler objects, it can often be best to use a structure instead of a class because the memory that they use is released immediately when the object goes out of scope. Just make sure that you understand how structures and classes behave differently. What Category (Managed/Unmanaged) Do Most Controls Fall Into? All Windows Forms controls use unmanaged resources because they wrap or are based on a Windows control. For the most part, all of your controls will be disposed automatically when the form is disposed (and the form is usually disposed when the user closes the form). The most common scenario where one might need to explicitly dispose of controls is when controls are dynamically created and destroyed. Other common classes that are disposable are FileStreams, DataBase objects, RegistryKeys, and web connections. How Do I Know If An Object Should Be Disposed? The easiest way to test this programatically is to see if an object implements IDisposable. [Color=Green]// C#[/Color] [Color=Blue]if[/Color](someObject [Color=Blue]is [/Color]IDisposable) someObject.Dispose(); [Color=Green]' VB[/Color] [Color=Blue]If TypeOf[/Color] SomeObject [Color=Blue]Is[/Color] IDisposable [Color=Blue]Then[/Color] SomeObject.Dispose() [/Code] Generally you won't find yourself doing this, though, because the code that created or acquired the disposable object will track it and dispose it when necessary. [b]How To Properly Write A Dispose Method[/b] First, the obvious. You should implement the IDisposable interface and create the Dispose method (sometimes it may be more appropriate to name this method a more descriptive name such as "Close" or "Release"). This method should release unmanaged resources and perform any necessary cleanup. Secondly, the not-so-obvious. The Dispose method should be programmed such that calling it more than one time should not cause an error. Also, unless there is a reason not to, the Dispose method should call the GC.SupressFinalize method (specifying itself) to inform the garbage collector that this object needs no further finalization. In fact, the finalizer almost always only serves the purpose of a fall back in case an object is not disposed. In your finalize method you should invoke the Dispose method. Many disposable objects use a slightly more complicated pattern. They implement IDisposable and have a Dispose (or Close) method, but they also have a private Dispose overload which accepts a boolean. The public Dispose method calls the private Dispose method and passes a true. The finalizer calls Dispose and passes a false. This boolean indicates whether the object is disposed explicitly (in code) or implicitly (by a finalizer). When the object is disposed explicitly extra cleanup can be performed, such as releasing references to other objects so that they may be garbaged collected sooner. This extra cleanup isn't necessary (especially when the object is disposed by the finalizer, since this often means that the program is closing anyways), but can improve garbage collection performance. This pattern should only be used when it represents a significant optimization. [b]Simple Tests To Determine If Your Objects Are Finalized And/Or Disposed.[/b] A good profiler would probably be helpful in this situation. Off the top of my head, another possibility would be to add debug code to track objects. For instance, a debug build of an application could use some static variables to count how many objects of a particular type are created, how many are disposed, and how many are finalized. You could go one step further and use a static dictionary object which stores stack traces to find out where undisposed objects are created. [b]Language Differences And IDisposable.[/b] The IDisposable interface is a .Net feature, not a language specific feature. Different languages have additional features, though, related to this interface. C# (all versions) and VB (version 8 and up) have "using blocks", where objects are disposed of when the scope of the using block ends or an exception is thrown. [code=csharp] using(FileStream someStream = new FileStream("C:\\textfile.txt", FileMode.Create)) { someStream.Write(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 0, 11); } // The stream will be closed when execution gets here. C++/CLI uses a modified destructor syntax to implicitly implement IDisposable. It is also worth noting that C# uses destructor syntax to implement finalizers, where as VB requires that users explicitly override the Finalize method. Any info that others wish to share is more than welcome.
    1 point
  3. C++ offers a special kind of type that is not present in C#: a union. For anyone who is not familiar with unions, here is a quick explanation of how they work and what they're good for. How They Work A union is somewhat like a struct. A union definition defines a type. A union type has fields and methods like a struct. The key difference is that a union stores all of its fields in the same memory location, whereas a struct stores each field in a different memory location. http://ilab.ahemm.org/imgHost/nonunion.gifhttp://ilab.ahemm.org/imgHost/union.gif What they are good for The primary use for a union is to conserve memory. Because the fields are stored in the same memory, generally only one field can be used at a time. Assigning one field changes the values of all fields, possibly to an invalid value. But, because all fields are stored in the same location, the size of the union is the size of the largest field, whereas the size of a struct is, at least, the total of the sizes of all fields. There is another use for unions too: treating the same binary data as different kinds of values. For instance, we could store an IntPtr in a union and then retrieve the value as a regular Int32. In other words, we can convert and dissect data with a union. Why Bother? Nearly any kind of conversion we could make through the use of a union we could make through the use of the Convert and BitConverter classes, so why bother using a union? Because it would be fast. The use of a union would be as an optimization. Although a union can occasionally produce less code than the use of conversion classes, the code tends to be harder to read and must be written with much more care because it can introduce kinds of bugs we aren't used to encountering. They should only be used when you really need the speed. And Now, For Your Viewing Pleasure If unions are a feature that is not present in C# then why did you read all that? Because unions are a feature present in the Common Language Runtime, and this feature can be utilized through the use of attributes, specifically the System.Runtime.InteropServices.StructLayoutAttribute and the System.Runtime.InteropServices.FieldOffsetAttribute. Where C++ uses the union keyword for unions, C# must modify a struct with attributes to produce the same behavior. System.Runtime.InteropServices.StructLayoutAttribute allows us to specify how, in memory, the fields of a struct will be laid out : automatically, sequentially, or explicitly. We are looking for the last of the three. When we are using an explicit layout, System.Runtime.InteropServices.FieldOffsetAttribute is the attribute that specifies where in memory the field will be. For instance, to view the binary value of a char as an unsigned integer, we could use the following struct: [structLayout(LayoutKind.Explicit)] public struct CharShortConverter { [FieldOffset(0)] public char Char; [FieldOffset(0)] public ushort UShort; // This method is not necessary to use a union, but it is very helpful because // otherwise we would have to explicitly initialize all the fields each time // we declare a variable of this type. public static CharShortConverter GetConverter() { CharShortConverter converter; converter.Char = ' '; converter.UShort = 0; return converter; } } This struct could be used as follows: // Get a converter CharShortConverter converter = CharShortConverter.GetConverter(); // Assign a char to the union, read it back as a UShort, and display the value. converter.Char = 'x'; MessageBox.Show(converter.UShort.ToString()); It would be much quicker, of course, to write code that used the BitConverter class, and usually much smarter, too. If, however, we had to convert a very large number of chars to ushorts, the use of a union could speed things up quite a bit. Instead of invoking a function we only need to assign a variable and read it back. Shortcomings The first shortcoming of this method is clearly visible in the first code listing. Because C# has no understanding of what a union is, it does not understand that assigning a value to one field initializes all fields, and so we must initialize the same memory multiple times to make the compiler happy. To make our lives easier, it is smartest to write a static method that will return an already-initialized variable. The second shortcoming is that, unlike C++, a C# union can't contain arrays. C# unions can't contain any reference types (reference types are garbage collected and structs are not), and arrays are reference types. This means that where in C++ we could access the bytes of an 64-bit integer by index, in C# we must declare eight fields and access them by name. A Useful Example The CharShortConverter isn't particularly useful, although I have a much more useful example, which is actually the reason I investigated unions in C# in the first place: image processing. When using unsafe code or the Marshal class to access raw image (as in the tutorial, Bitmap Manipulation) data it is very handy to have a quick way to access the individual color components of each pixel, and so we have the Pixel struct. // Represents a 32-bit ARGB pixel // Allows pixel data to be accessed much faster than via // the Color struct or the BitConverter class. [structLayout(LayoutKind.Explicit)] public struct Pixel { // Composite ARGB value [FieldOffset(0)] public int ARGB; // Color components [FieldOffset(3)] public byte A; [FieldOffset(2)] public byte R; [FieldOffset(1)] public byte G; [FieldOffset(0)] public byte B; // Method to get an instance of this union public static Pixel GetPixel() { Pixel result; result.A = 0; result.R = 0; result.G = 0; result.B = 0; result.ARGB = 0; return result; } // Set this union to represent the specified color public void LoadColor(System.Drawing.Color c) { ARGB = c.ToArgb(); } // Create a Color struct that represents this union public Color ToColor() { return Color.FromArgb(ARGB); } }
    1 point
  4. With help from this forum I was able to figure out the double buffer solution using gdi32's BitBlt in C#.net. GDI+ is well known for its lack of speed in the performance arena. To solve the "flicker" solution, and add a fast back buffer to my application, i dipped back into gdi32. What you'll want to do is this.. On your form, create a picturebox that will show your live drawing. Lets call it picChart. Now, what we need to do is create a back buffer for our picChart. private Bitmap memBmp; // Backbuffers bitmap private IntPtr hMemBmp; // Handle to our memBmp private Graphics memDC; // We draw on this private IntPtr hMemdc; // Handle to our memDC private void picChart_Resize(object sender, EventArgs e) { // If we have already created a dc for mem, lets free it up first if (hMemdc.ToInt32() != 0) { // Clean up DeleteObject(hMemBmp); DeleteDC(hMemdc); memBmp.Dispose(); } // Resize our backbuffer memBmp = new Bitmap(picChart.Width, picChart.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555 ); Graphics clientDC = picChart.CreateGraphics(); IntPtr hdc = clientDC.GetHdc(); hMemdc = CreateCompatibleDC(hdc); // hMemdc is the handle to our memDC hMemBmp = memBmp.GetHbitmap(); SelectObject(hMemdc, hMemBmp); memDC = Graphics.FromHdc(hMemdc); // We draw on memDC // Clean up clientDC.ReleaseHdc(hdc); clientDC.Dispose(); } private void picChart_Paint(object sender, PaintEventArgs e) { // Copy Region from memDC IntPtr hdc = e.Graphics.GetHdc(); BitBlt(hdc, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height, hMemdc, e.ClipRectangle.X, e.ClipRectangle.Y, 0x00CC0020); e.Graphics.ReleaseHdc(hdc); } What the above code does is create a backbuffer the same size of our picChart every time the picChart is resized. If we have already created a backbuffer from a previous resize event, we delete the previous backbuffer from memory. Then in the picChart paint event, we will bitblt the exact region that was invalidated to our main picChart paint area. Also, in your form/controls dispose() method you will need to add: // If we have already created a dc for mem, lets free it up first if (hMemdc.ToInt32() != 0) { // Clean up DeleteObject(hMemBmp); DeleteDC(hMemdc); memBmp.Dispose(); } That will free up your backbuffer if it was created before the form/control disposes. To draw on your backbuffer, all you have to use is memDC.Drawxxx to draw whatever you like. It still uses GDI+ drawing techniques but will use the faster gdi32 bitblt to doublebuffer and repaint your form. Hope this helps.
    1 point
  5. Visual Basic .NET Standard Edition doesn't come with very many project types, so I decided to add a few more using the VS.NET project scripting system. The .zip file below explains how to install the necessary files. They'll add "Class Library" and "Windows Control Library" to your list of available project types. Note: Files will need to be modified for non-English (1033) installations. newprojects.zip
    1 point
×
×
  • Create New...