- 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
That's horrible because RegistryKey is an IDisposable object; not only will you run into memory leak issues, the numbers of handles are also limited.
The correct code would be:
Admin
@MaxiTB - MOST IDisposable do not actually keep a reference to an unmanaged object. Therefor implementing IDisposable is the WRONG approach. Also implementing IDisposable does not do anything... it merely requires you write a method named Dispose...the system will NEVER call it automatically... You could write a method call FooMe and call it in all of the places where you would have called Dispose... Further, it must be legal to call Dispose multiple times, but accessing ANY other ember must throw an ObjectDisposedException... and ANY class which has an IDisposable Member must also implement IDisposable...
In 2022 I led a team of 3 developers, took 19 man months!!!! to eliminate incorrect IDisposable from their code, and encapsulate/abstract all of the incorrect implementations in the .Net Framework and NuGet package..
Admin
Add to the first example, I'd be extremely surprised to find a compiler that didn't convert any pure mathematical expression with known values to a constant during compilation. This syntax is common as it clearly indicates the bit position being tested in a bit field. Guess must be fresh out of the college dorm.
Admin
Users who have been instructed to create HTML pages should have been instructed which editor to use. So, still a WTF.
Admin
I was going to comment that the finalizer will dispose it for you (upon GC), but it looks like RegistryKey doesn't have a finalizer? In .NET Framework, there's a Dispose(bool) method, but no finalizer with a Dispose(false) call??? And in .NET Core, they've removed that indirection!
.NET Framework: https://referencesource.microsoft.com/#mscorlib/microsoft/win32/registrykey.cs,7fd1b519e6923ca5
.NET 8: https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs#L128-L163
Admin
"Sometimes, we have a broken world that we can just do our best no navigate"
I guess i'll navigate past the n-t mixup just before "navigate" :^)
Admin
What these submissions - and to be fair, almost everything that ends up on this site - really show is that the world seems to be filled with people doing things that they don't really understand - they're just fudging their way through in a blind panic, randomly changing things until the errors go away.
Has it always been this way or has it just reached a point where it's become the norm rather than the exception?
Admin
I'd argue that it's always been that way. A good rule for life, which I learned from TDWTF, is this: if you show up, do the work, and are halfway competent, you are light years beyond the competition already. The world doesn't need more geniuses, it just needs more competent people.
Admin
#define FEATURE_SENSE_CHAN (1 << 0)
Aaaand now I'm visualizing an anime starring "Feature Sense-chan".
Admin
I think it's because they realized that since they're using a SafeHandle already, there's no need for a finalizer in a class that doesn't manipulate directly an unmanaged resource's lifetime.
Only the SafeHandle class should have a finalizer (that takes care of calling
CloseHandle
) since it's the one managing the lifetime of an unmanaged resource.Admin
It goes with the mangled grammar in the first sentence of Remy's intro.
Admin
It may be minor, but C# has very simple and clearly defined naming conventions, so an upper camel cased local variable like "BoolLog" is definitely a WTF.
Admin
I know exactly how this happens, because it happened to me.
We had a legacy application that was a hodgepodge of C#, VB6, and a few minor scripts.
It would save settings in various places. INI files, database, .config files, and yes, registry.
If you changed a boolean setting value and converted it to a string, the result would be different. For example, "true" in VB6 is "-1". Which makes a weird kind of sense - all bits are set to 1.
And then you'd have people manually changing values. Telling someone "set that value to true" could result in "true", "yes", "1" or something else.
So deep in the code, in a "GetSettingValue<bool>" method, I had to handle booleans a bit differently. "ON", "TRUE", "T", "YES", "Y", "1" and "-1" would return true. Anything else returned false.
Admin
Could it be that rather than people getting dimmer, this stuff is getting over complex? I realise that the current world of development is far more complex than the world I started my career in (Mailframe PLI) as we are developing on, with and for more capable environments and creating far more complex solutions, but I do wonder if these modern tools and languages and environments are not just making stuff too complex for humans to understand and explot - and debug - and I lean on the whole of WTF as my evidence for this hypothesis.
Admin
It has been my experience that most developers work this way. I really appreciate it when I see bad code and it has the same variable names as in the Stack Overflow highest rated answer for a question vaguely related.
I just had an issue this morning where a developer used a pile of global variables in a chuck of code that processes a file. Shockingly, under an uncommon set of circumstances, one of the variables carried over a value from the previous record. We couldn't get it through the developer's head that the actual problem was the global variables, not the specific bug that happened this time.
When I see new feature introduced in my development ecosystem, I can usually see the progression from problem to solution. 90% of the people I interact with didn't consider the original problem and don't see the value of the solution.
For example, C# fairly recently introduced default interface implementations. The first thing I thought was that for my frequently-added-to interfaces, such as database repositories, I can just add an interface method with a default implementation of "throw new NotImplementedException();", and I can avoid compile errors from other consumers of the interface. In the past, I would have had to make a base class that implements everything and have consumers inherit the base class rather than directly implement the interface. The new pattern is less work, less likely for people to get wrong, and looks more correct.
Admin
The point of IDisposable is to dispose unmanaged resources as soon as possible. Finalizers are called by the garbage collector - there is no guarantee when, in fact, if the objects ends up as a gen-2 object, it will only be called when the process gets terminated. The disposable pattern recommends overwriting the finalizer and recommends allowing multiple disposing, but those are not mandatory - in fact many old IDisposable objects in the framework didn't implement the recommended parts of the pattern, most famously the old XML library. When an object is IDisposible, you have to dispose it as a consumer as soon as possible in an exception safe way, period. That is the rule, it doesn't matter what Dispose implements (see https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/using-objects) ;-)
In .net Framework days RegistryKey relied on the Win32 SDK for access to the registry, using the registry handles. Those get cached, so it is critical to release them to allow the cache to flush.
With netcore Registry parts got reimplemented in a open source non-properitary way, so it's implementation is slightly different. But the usage is the same and as mentioned above, it's not about the implementation, IDispose is a contract, you have to correctly dispose the object.
Admin
It doesn't matter how it is implemented. IDispose is a contract, it has to be disposed correctly (see https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/using-objects). It's up to the creator to the component to make use of the contract the way the creator sees fit. As a consumer of the object, it is your responsibility to follow the contract because you don't even know that will be behind Dispose tomorrow.
IDisposable is a contract that exist since .net 1.0 for handling eager cleanup operations. It doesn't matter what the method implements at this point, if the object has an IDisposable, you have to dispose of it correctly as a consumer of said object (see https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/using-objects). It's exactly the same way as you have to free memory after you alloc it in C; those are also just functions, the contract demands of the consumer to free the object as soon as no longer required.
This is incorrect. Dispose SHOULD allow to be called multiple times, but there is no requirement for this and never has been. In fact it is wrong to rely on this. Since netcore it is best practice to do it, but not required (see basic dispose pattern https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern). There is still a ton of Disposable objects around in various libraries that don't support multi-disposing, especially when it's thin COM+ wrappers.
Admin
I have a gripe with the article rather than the presented code.
I don't believe the Registry was ever intended to actually be an optimum solution for storing configuration. Rather, it was intended to make it impossible to copy an existing software installation--an anti-piracy measure.
Admin
My understanding is the Windows Registry was created to solve the problem that FATnn filesystems on 90s hard drives meant even a small .ini file would use a relatively large amount of space. That benefit hasn't been remotely relevant for at least a decade and all that remain are the problems.
Admin
The first one is a WTF
Here's a fix
Joking aside, I think I need more context as somebody who knows nothing about Internet telephony. Is it possible for both to be true or for neither? If not, I would argue that the state is modelled in a WTF way.
Admin
This seems unlikely. In what way does the Registry combat piracy?
According to Raymond Chen [1], the advantages of the Registry over INI files are:
[1] https://devblogs.microsoft.com/oldnewthing/20071126-00/?p=24383
Admin
IDisposable
has always been a difficult contract to do right. Looks simple, but not so much in reality with complex objects which may hold quite a graph ofIDisposable
objects but themselves do not hold unmanaged resources directly. Collections ofIDisposable
whatevers are especially un-fun.Beyond that an object upon which
Dispose()
has been called must fire anObjectDisposedException
on every single property access or method call. And for completeness, must have no non-private fields. The compiler provides no help for implementing that, and all the handy shortcuts for property definition must not be used if the object implements IDisposable.@CPUWizard misses the point that the system never calls
Dispose()
. It's not expected to. It's part of the object consumer contract to callDispose()
. Not part of the GC's contract, nor any other backstage process.Admin
Oops. Meant to have more in the second paragraph. The "useless after Dispose" feature is a misfeature for lots of use cases where you might want a long-lived object which populates and depopulates various either IDisposable objects or unmanaged references. Essentially you're forced to build things that can be
Close()
ed, but never re-Open()
ed. Which depending on how heavy they are may be utterly the wrong design decision.I totally get why IDisposable was needed even from .NET Framework 1.0. It's a shame they haven't come up with a different IDisposable2 that encompasses the lessons learned in the intervening 20+ years.
Admin
Can someone explain why people think the Windows registry is "a nightmare" to work with? Especially given all the above benefits.
In all my years of working with Windows desktop apps, I've never had a problem with the registry. It's a wonderful place to store your app's config in a typed (well, except for boolean), hierarchical way.
What's the alternative? Text files?
Admin
Works fine for Linux and MacOS.
Also worked just fine for Windows prior to 95.
Fun fact, Windows 3.11 actually had a registry too, it had regedit.exe and reg.dat, but the only thing MS stored in the registry was file associations.
Admin
What works fine? Linux and MacOS don't have a registry?
Or are you just suggesting that text files are the way to go? Because I hear a lot of hate about JSON and other formats from people on this site and on that I can agree. Text files have no defined format (so you end up re-inventing the wheel every decade or so - xml, json, yaml, etc) and have no data types so you have to decide how a date, number, etc should be stored.
Again, why is the Windows registry horrible?
Admin
It's not the registry per se, but I don't care for the fact that RegEdit saves changes automatically, and does not show you a diff of the changes before saving.