- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Meh. Today's article was a lot of buildup to something that would otherwise just be one item in one of those "Look at these funny function names" articles.
Admin
Which tyranny that is Hungarian Notation?
That is, "applications" or "systems" HN. Systems HN is a crime against humanity. (It is the origin of the w in wParam, "word Parameter" versus the l in lParam, "long Parameter", doubly distressing since wParam is no longer a WORD.)
Applications HN says that the wart shows information about the variable that is not captured, as such, in its type. Example: cbFribble is a count of bytes somehow linked to fribbling. We know it's an unsigned type of some sort from its declaration, but the "cb" adds the information that it's a byte count.
More ... enlightened ... languages than C can do this by having proper separation of types (XMLSanitizedString, HTMLEncodedString, UntrustedString, NonEncodedString), but that's the origin. Someone (else) at Microsoft got hold of this idea and mutated it into what we see now as Systems HN, where people say "int iNum" as if the "i" in "iNum" actually adds something (instead of encoding the "fact" that iNum is an int). And, worse, they end up with variables whose name is just the wart. How many programs contain declarations like "HWND hwnd;"?
Admin
To this day I always thought LPARAM meant "Left Parameter" and WPARAM meant "Some-Foreign-Word-Translating-To-'Right' Parameter".
Anyway, I've no particular problem with hungarian notation, but a decade of interaction with insufferable Apple fanbois has given me an intense revulsion for anything prefixed with a superfluous "i".
Admin
No FristSuckingPigDogs today?
Admin
LPARAM is long pointer to ARAM
Admin
HWND - handle to a Windows-Object - basically a pointer - That was a good mind-bendig abbreviation.
But the best of all hungarian notations and most used one in the Microsoft Foundation Classes is: LPTCSTR
Long pointer to a text-character c-style string. Text character means Unicode. And a C-string is 0-terminated and different from a B-string.
Admin
That hurts my c-string
Admin
What about "spunk"?
http://tinyurl.com/jj954cj
Presumably a "short pointer" to Unknown.
Or "SHITEMID" - a "short handle" to an Item ID?
http://tinyurl.com/zpmr2wp
Admin
Actually, the extension method has one advantage over calling .Dispose() directly, in that it will also work on classes that implement IDisposable explicitly.
Implementing an interface explicitly means the methods don't show up on the normal class, possibly because there are name conflicts that would arise if you did so, BUT you can cast to the interface type and then use the methods from there. This extension method allows you to do that in one step.
But yeah if you have control over the class code, you can just code in a method directly that casts its own instance and calls .Dispose(). Extension methods are intended for classes you can't modify directly (eg sealed, closed source, etc).
Also, "Finalize" is only a thing in VB.NET. In any other sane language (C#) it's called the destructor.
Addendum 2017-02-01 07:52: [Edit: Actually, I'm not sure if the extension method would be callable without casting. I've never tried anything like this!]
Admin
To this day I always thought LPARAM meant "Left Parameter" and WPARAM meant "Some-Foreign-Word-Translating-To-'Right' Parameter".
Actuawwy, dat's wight.
(Yes, Googwe, I'm no wobot.)
Admin
Abstract RAM, the next step after virtual memory.
Admin
TRWTF is calling C# .NET
Admin
While this is correct, it's sidestepping the point that you almost never should call Dispose directly. You should be using "using". The only common use case for this extension method that I can see is that it saves you a cast when implementing Dispose - and it does so at the cost of some obfuscation, not a good tradeoff IMO.
Except C++. Where "destructor" is already a thing. So "destructor" means "Dispose". :/
Admin
Hate to be the pedant of the bunch, but nobody else has mentioned it yet:
You can't declare extension methods in any class... You can only declare them in a public/internal static class.
Admin
SHITEMID stands for Shell Item ID. Explorer is essentially the shell UI. And Windows Explorer is as well, but with a specific purpose.
An SHITEMID could represent a file, a directory, or one of the "virtual" directories: Desktop, My Documents, etc. It was while working with the shell that I came to the conclusion that's why Windows started referring to directories as folders.
A directory is a "physical" location, but a folder doesn't have that limitation. The directory it represents can be different. A good example of this would be the Desktop folder. There's a specific SHITEMID for it, but the physical location is different depending on who's logged in.
Admin
Damn, this soapbox is getting dirty. I think I'll Dispose of it.
Admin
"almost never should call Dispose directly. You should be using "using""
There are plenty of times you need to call Dispose directly, which is basically when using "using" does fit. One obvious situation you have to call Dispose would be when you're implementing it: you need to call Dispose() of any data members.
or if the disposable object is returned from a method. The disposable object gets created and before being returned some further work is done, which could result in a exception being thrown. In the catch block, you would need to call Dispose()
"Except C++. Where "destructor" is already a thing. So "destructor" means "Dispose""
Good ol' C++. I miss C++ destructors. The closest thing you can get in .NET is a try/finally. Anyway, a C# destructor does not mean Dispose(). C#'s destructor is how you define an object's finalizer. It's the equivalent of VB.NET's Finalize(). Dipose() is meant to cleanup/release managed resources, which helps making objects available for garbage collection sooner. The finalizer gets called by the garbage collector after collection and is meant to cleanup/release unmanaged resources.
Best practice for implementing Dipose() is that if your object doesn't use any unmanaged resources, you tell the GC not to bother calling the finalizer via GC.SuppressFInalize()
Admin
The way I do it is,
Dispose
cleans up all resources, managed and unmanaged, and callsGC.SuppressFInalize()
. The destructor throws, because if it's getting called, that means you forgot to callDispose
somewhere, which is a bug, so you need to call attention to it and fix it.Admin
.NET is a language?
Admin
Yep. And so is 'murican.
Admin
Weird. We had code exactly like that at the last job I worked at. And a guy named Kaleb. What a coincidence.
Anyhow, 2009 called and wants it's article back: https://blog.codinghorror.com/die-you-gravy-sucking-pig-dog/
Admin
The I makes sense in a way. You can tell at a glance if an inherited symbol is a class (limit 1) or an interface (unlimited).
Java took a different route by using different inheritance keywords for classes (extends) and interfaces (implements).
It also helps in cases where an implementation and interface would otherwise have identical names (i.e. IList<T> and List<T>).
Addendum 2017-02-01 10:49: Gotta love how the edit button doesn't let me modify what was already in my post to fix the comment parser not like less-than signs.
Admin
There are use-cases for that still. Consider:
Admin
Finalize is also a thing in Ada. It is procedure that performs finalization on object of given type. Also: Object is an entity of given type. Although in other languages you call that destructor. Dunno what objects are in other languages.
Admin
The concepts talked about apply to most .Net languages. IDisposible is part of the framework and, therefore, applicable to all .Net languages. I believe the extension methods are fairly common as well, though I do believe it is language dependent. VB.Net and C# both implement the extension method concept, and can use extension methods from .Net libraries built in other .Net languages.
So, while the examples are C#, everything is applicable to most .Net languages... though I have little experience with IronPython, F#, Cobol.Net, etc.
Admin
What are you pedanting about exactly? I don't see anyone claiming that you can declare extension methods in any class.
You can declare extension methods of any class.
Admin
Joel's rundown of systems vs. application HN is pretty great:
https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/
Admin
It's possible this is a relic of a wrestling match Kaleb's co-worker had at some point in the past with the .NET framework's numerous garbage collection bugs in versions 1.0 and 1.1.
If so, the sad part is that it was left in because he went on to try other fixes after it didn't help.
Admin
Actually, the T is platform specific. The default is ANSI, W is for Wide/Unicode.
Admin
Not familiar enough with C#, but I gather IDisposable is essentially the same concept as Closable / Autoclosable in Java? Essentially, it signifies that the class holds onto resources that need to be cleaned up - allowing it to participate in language features for cleaning up on scope exit (instead of GC), and allowing for tools like IDEs to help spot resource leaks?
Admin
Spunk? Also a Danish licorice...
Admin
Of course, in Java every damned class is a AbstractSomething or SomethingImpl anyway. Why do Java people love Impl so much, when the standard library never once uses it? Who knows.
Admin
Because they tend to shy away from the "I" prefix for interfaces, so you have Widget (interface) and WidgetImpl (class). Personally, I prefer IXxx and Xxx, but that's just me.
Admin
Actually "HWND hwnd" isn't the best example of using just the wart. The best one is "int i", if you think about it.
Admin
Woof.
Admin
This code looks fine to me. It actually looks even better than just calling .Dispose(), because it indicates to future maintainers that there's some issue with the object or the disposal of the object - it's a big "tread cautiously" sign. At worst, it's something that puts a smile on someone's face, with no adverse consequences.
I guess the submitter has a stick up their butt about Enterprise Code Standards or the like? I'm all in favour of removing pointless obfuscations that add nothing, or removing complicated workarounds. I see nothing wrong with this, though.
Admin
Almost but not entirely right (you forgot the C means const):
LPCTSTR = Long Pointer to a Const TCHAR STRing
Admin
If you implement Dispose privately, that means you're {re,ab}using the built-in interface for something other than the one thing it's supposed to be used for. So make another interface and use that.
Admin
Plus, that part is not the "Systems Hungarian Notation" part. The "Systems Hungarian Notation" part is when this type is later used to declare a LPCTSTR lpszString;
Admin
"But the best of all hungarian notations and most used one in the Microsoft Foundation Classes is: LPTCSTR
Long pointer to a text-character c-style string. Text character means Unicode. And a C-string is 0-terminated and different from a B-string."
Almost. the 'T' stands for TCHAR, which is a Microsoft abomination whose type depends on a preprocessor definition. If UNICODE is defined, it evaluates to wchar_t; otherwise it's a plain old char. Better hope all your objects are compiled the same way...
Admin
I have another theory: It was a poor BSD programmer, who was forced to work not only on a sub-par operating system, but on .NET no less. And so he vent is frustration, mixed with longing for what he'll never have again in his day-job. Fun.
Proof: https://svnweb.freebsd.org/base/stable/11/sbin/shutdown/shutdown.c?revision=302408&view=markup#l354
Admin
Your comment is the first genuinely insightful thing I've read on this thread. Makes total sense. Put a throw in the finalizer and that way you know when dispose hasn't been called. Might save ages messing about with the memory profiler to find leaks.
Admin
Years ago I wrote a rant on Hungarian notation. If you read Simonyi's thesis, his idea makes perfect sense in languages like C that have limited capability for defining new types.
What Microsoft did makes no sense at all, and clearly demonstrates that whoever came up with the implementation flat-out didn't understand what Simonyi was talking about.
Simonyi advocated for prefixes that represent the logical type of a variable. So ints containing colors and ints containing automobile models and ints containing dog species would have different prefixes. MS decided, in it's wisdom, to define prefixes for the physical representation of a variable, so colors and automobile models and dog species would all be prefixed with "i". Not only is this pointless, it's encoding in the name precisely what you don't want to be encoding in the name.
http://forums.devx.com/showthread.php?2179-Hungarian-naming-convention
Admin
Has no one else noticed that the theory that LParam stands for left parameter fails immediately due to the fact that lParam is the rightmost parameter?
Admin
"using" only works if you have a linear execution path.
If your class leaves a file open so that future method calls can access it then you're going to end up implementing and calling dispose (although on a file, you'd normally call close).
Admin
LOL! Um, if I were as you described, I would be removing the "offending" code, not submitting it to a website for laughs. ;-)