Posted By: SEP2007 | Jan 25th, 2007 @ 9:56 PM
page 1 of 1
Comments: 21 | Views: 7747
SEP2007
SEP2007
"Give Everything Its Home"
Can anyone tell me why in VB I have to go

Me.RichTextBox1.Font = New Font("Times New Roman", 12, FontStyle.Regular)


And not

Me.RichTextBox1.Font = Font.Times New Roman

or

Me.RichTextBox1.Font = Font("Times New Roman", 12, FontStyle.Regular)



Jorgie
Jorgie
Jorgie
You have to do it that way because you are not just plugging the name of a font into a text field, you are assigning a resource to the RichTextBox.

You have to actually create an instance of a font object and then point the RichTextBox at it.

Yes it seems more complicated, but it also means that you can do things like have multiple controls use the same instance of a font object, not make their own copy among many other things.

The same is true for many things, like mouse cursors.

Jorgie
amotif
amotif
No Silver Bullet
SEP2007 wrote:
But if the rich text box has a font object *as part of it* (?)

I.e. it uses a font object within its make-up

Why can't I access that ?


But you can access it, the RichTextBox.Font property has both a getter and a setter. However, if memory doesn't fail me, the Font class is immutable--you can't change the Font object's fields. So you can't just set Font.FontFamily. You have to create a new instance of Font and set that on the RichTextBox. That's a feature of Font, not RichTextBox.

This probably works out well for RichTextBox, as it would like to know when the font changes, so forcing you to use a setter makes it clear when the font changed. Hypothetically,

class RichTextBox
{
    Font Font
    {
        set
        {
            // Ah, we're changing the font!
            _font = value;
            InvalidateLayout(); // Force a layout and redraw.
        }
        get
        {
            return _font;
        }
    }
}

Or some such thing.
W3bbo
W3bbo
The Master of Baiters
SEP2007 wrote:
a bit confused now.


i understand that I could in theory,

*set* the font name.

and that doing so I would have to , inform the r.t.b to update itself.

I just don't really, (or am trying to) understand *why* i have to do it that way [ first message ] .

I seem right to do it that way.


From the looks of things, you're not familar with OOP (and VB6/VBS is not OOB), I recommend you start looking at the concept of Types too (a prerequisite to OOP)

Then you'll understand.
Jorgie
Jorgie
Jorgie
Lets try a silly example.

You want to change the tire on your car. You can't just erase the name FireStone and write in GoodYear, it would still be the same tire. You have to get your hands on a New tire to replace the old one.

The New method takes care of creating an instance of an object by allocating memory and any other resources needed by the object. If I am not mistaken, the opposite of New in managed code is Dispose, but you don't have to worry about directly calling Dispose most of the time, as the runtime will call the object's Dispose method when it is no longer needed.

Like the tire I mentioned above the font object tied to your text box is a 'specific instance' of a font. To replace it, you have to remove it and provide a new one.

It is true that they could have over loaded the text box's font property to take a string that is the name of the font and then create new font resource and use it, but like many changes made to make things easier, that would take some control away from the programmer. 

For example if you needed to switch back and forth between two fonts and the text box just took the name and size of the font and loaded them for you, it would be creating a new instance of the font every time you switched to it: (yes this is just pseudo code.)

tb1.font = "Arial 10pt";
// new Arial font object created
tb1.font = "Times 10pt";
//Arial font object thrown away, new Times font object created
tb1.font = "Arial 10pt";
//Times font object thrown away, new Arial object created

The way it actually works, you can just create the two fonts once, and switch between them: (again this is just pseudo code.)

Font fArial = new Font("Arial",10);  //create new Arial font object
Font fTimes = new Font("Times",10pt); //create new Times font object
tb1.font = fArial; //switch to Arial font, no new objects created
tb1.font = fTimes; //switch to Times font, no new objects created
tb1.font = fArial; //switch to Arial font, no new objects created

Hope that helps.

Jorgie

W3bbo
W3bbo
The Master of Baiters
Jorgie wrote:
The New method takes care of creating an instance of an object by allocating memory and any other resources needed by the object. If I am not mistaken, the opposite of New in managed code is Dispose, but you don't have to worry about directly calling Dispose most of the time, as the runtime will call the object's Dispose method when it is no longer needed.


Dispose is only used by IDisposable for unmanaged resources used by managed classes. Whilst managed code has destructors, these are always called by the GC and not the user. Unlike C++ where you needed to call delete every time you called new, the CLR GC does this at the next GC interval once an object has no references to it.
W3bbo
W3bbo
The Master of Baiters
Jorgie wrote:
The New method takes care of creating an instance of an object by allocating memory and any other resources needed by the object. If I am not mistaken, the opposite of New in managed code is Dispose, but you don't have to worry about directly calling Dispose most of the time, as the runtime will call the object's Dispose method when it is no longer needed.


Dispose is only used by IDisposable for unmanaged resources used by managed classes. Whilst managed code has destructors, these are always called by the GC and not the user. Unlike C++ where you needed to call delete every time you called new, the CLR GC does this at the next GC interval once an object has no references to it.
Jorgie
Jorgie
Jorgie
W3bbo wrote:

Dispose is only used by IDisposable for unmanaged resources used by managed classes. Whilst managed code has destructors, these are always called by the GC and not the user. Unlike C++ where you needed to call delete every time you called new, the CLR GC does this at the next GC interval once an object has no references to it.


That is strange. I use dispose on the fully managed Image object all the time. Using it seems to get old images cleaned up by the GC much faster.

For example, I have a little tasktray app that is always running and changes my desktop every 15 minutes. Because XP wanted BMP files and most of my images are jpgs, I use an Image object to load the jpg and save it as a bmp in my profiles temp folder to be used as the current desktop. Even though the Image object goes out of scope right after I finish with it, if I don't call the images dispose function my memory use grows to 128MB or higher after running for 24hours or more. Once I started using the image objects dispose function, the application never uses more than 4BM.

So there seems to be times when Dispose is useful even for manage objects. (It could be that having 2GB of RAM gives me enough headroom that the GC does not think it needs to be cleaned up.)

It would be nice to know if there are any reasons NOT to use Dispose in cases like this because even the Image object documentation says "This member supports the .NET Framework infrastructure and is not intended to be used directly from your code" But does not elaborate.

Jorgie
Jorgie
Jorgie
Jorgie
HMMM... now I am really confused, as I just found this:

When and How to Use Dispose and Finalize in C#

And it says:

The Dispose Method—Explicit Resource Cleanup
Unlike Finalize, developers should call Dispose explicitly to free unmanaged resources. In fact, you should call the Dispose method explicitly on any object that implements it to free any unmanaged resources for which the object may be holding references. The Dispose method generally doesn't free managed memory—typically, it's used for early reclamation of only the unmanaged resources to which a class is holding references. In other words, this method can release the unmanaged resources in a deterministic fashion.

So I need to find more info on Dispose.

Jorgie
The Dispose method is used to release resources used by objects, while it's true that you can wait for GC to invoke the finalizer it's generally better to release resources you have obtained as soon as you finish with them, especially when the resource you have is particularly expensive or scarse, this is because you have no control over when GC invokes the finalizer, it could be five minutes, or fove hours.
stevo_
stevo_
Human after all
Personally I was going to say finalize was the 'other side' of the constructor. Rather than Dispose, which is a method of granular resource cleanup, such as freeing up unmanaged objects.

I could be wrong, but I've generally looked at it that way.
Yggdrasil
Yggdrasil
Pour me a cab, 'cause I can't drink no more.
Jorgie wrote:
 Even though the Image object goes out of scope right after I finish with it, if I don't call the images dispose function my memory use grows to 128MB or higher after running for 24hours or more. Once I started using the image objects dispose function, the application never uses more than 4BM.


There's a difference between managed objects and managed memory. Even though Image is a managed class, it holds unmanaged resources (in this case, a handle to a GDI object where the bitmap is actually mapped. You can see this by opening Reflector and looking at the Dispose(Boolean) and FromFile(string) methods on the Image object. Lots of unmanaged memory mapping going on.

Same thing goes for Stream objects - the object itself is managed, but it holds unmanaged resources (file handles and locks, in this case).

In general principle, you can assume that if a framework class implements IDisposable, it probably holds some unmanaged resource and you SHOULD call Dispose() if you know you're done with it. When in doubt - Reflector. Smiley
W3bbo
W3bbo
The Master of Baiters
Yggdrasil wrote:
In general principle, you can assume that if a framework class implements IDisposable, it probably holds some unmanaged resource and you SHOULD call Dispose() if you know you're done with it. When in doubt - Reflector. Smiley


Or better yet, just use C#'s using(){} block.

page 1 of 1
Comments: 21 | Views: 7747
Microsoft Communities