1

Here's where .NET starts to do my head in. Consider the following scenario:

  1. I have a DataTable object, containing a number of DataRow objects
  2. I add some of the DataRow objects to an Array
  3. I call Dispose on the DataTable.

What guarantee do I have that calling Dispose on the DataTable won't compromise the DataRow objects (which, by reference, would affect those added to the Array)?

MS documentation is zero help in this case.

EDIT: So far folks have missed the point entirely. IDisposable objects are meant to be disposed of as soon as possible. My code is going to be creating thousands of DataTable objects during a typical day. No way am I leaving those un-disposed if they implement IDispoable.

BUT, I need the handful of DataRow objects to stay alive because that's what my 3rd-party binary (which I have no control over) expects. And I need them to stay alive for significantly longer than the DataTable objects.

All I need is authoritative information that describes what Dispose on a DataTable actually does. Looks like said information does not exist, which is why I'm asking here for help. Someone may have a reference, or documentation I have overlooked, that answers my need.

EDIT 2: I have tested as Blam suggested, including adding GC.Collect + a bonus GC.WaitForPendingFinalizers + one more GC.Collect after disposing the DataTable. The DataRows appear to be fine, still alive and accessible. That's positive, but alas not authoritative enough to include in production code :-(

misha256
  • 337
  • 3
  • 16
  • 4
    What do you mean by "compromise"? If you still want to use the `DataRow` objects then why are you disposing the `DataTable` that contains them in the first place? Disposing something is only to be done when you have no further use of it. If you do have further use for the `DataTable` then don't dispose it in the first place. – jmcilhinney Jun 22 '15 at 00:54
  • 1
    What do you gain in keeping the DataRows in an array? – Tarik Jun 22 '15 at 00:57
  • 1
    @Tarik I gain compatibility with a method (3rd-party binary) that expects DataRows in an Array ;-) – misha256 Jun 22 '15 at 01:10
  • @jmcilhinney. Exactly. I *don't* have any further use for the `DataTable`, I only have use for the handful of `DataRows` in the Array. That's why I want to Dispose of the `DataTable`, but only if it leaves the `DataRows` unaffected. – misha256 Jun 22 '15 at 01:45
  • 1
    @Blam End-user testing to determine undocumented behaviors is dangerous. What is system configuration / resource pressures on another machine cause GC to behave differently or more aggressively than in my tests? – misha256 Jun 22 '15 at 01:51
  • Did you test? Did you call a GC.Collect? – paparazzo Jun 22 '15 at 01:57
  • @Blam You've got to be kidding. Is this how you code? Second-guessing someone else's hidden/undocumented behaviors by running your own tests is *not* going to result in robust, dependable apps. – misha256 Jun 22 '15 at 02:11
  • @misha256 Are you kidding? Is that how you go about not testing? Did you test a Dispose and GC.Collect or not? – paparazzo Jun 22 '15 at 02:14
  • 1
    @Blam You're missing the point. What guarantee do I have that my test results would actually be correct (repeatable, dependable, system-agnostic, etc.)? Of course I test, we test all the time. But NOT to try to reverse-engineer undocumented behaviors. Like I said, that's dangerous and we don't do that. Why don't we just stick to my question which I now clarified. – misha256 Jun 22 '15 at 02:20
  • Of course you test? You give NO indication of what you have tested. What is the problem with stating in the question what you have tested? – paparazzo Jun 22 '15 at 02:31
  • @Blam OK I concede! I have tested as you suggest, including adding `GC.Collect` + a bonus `GC.WaitForPendingFinalizers` + one more `GC.Collect` after disposing the `DataTable`. The `DataRows` appear to be fine, still alive and accessible. That's positive, but alas not authoritative enough to include in production code :-( – misha256 Jun 22 '15 at 02:42

2 Answers2

3

DataTable doesn't re-implement MarshalByValueComponent.Dispose, and that method doesn't really do much on its own. So in effect, calling DataTable.Dispose doesn't do anything to the table or the data it contains. Interestingly enough, DataTable even goes so far to suppress finalization in the constructor, because it doesn't hold unmanaged resources.

Now, if you look at the definition for DataRow, you'll notice that it doesn't implement IDisposable (or anything for that matter), doesn't have a finalizer, etc. It does, however, have a dependency on the table (which it gets via the DataRowBuilder passed in the constructor). Normally in that sort of situation, you never want to call dispose on an owning object until absolutely no one needs it anymore, as it could result in side effects from that parent reference being disposed of already.

However, in this case calling dispose doesn't actually do anything and it doesn't matter either way. In fact, you're calling Dispose as a premature optimization that has little or no effect, so it's superfluous. Your DataRows and the data they contain will be unaffected by calling dispose on the table.

(Sorry but not sorry the example is C# and not VB.NET, but there is no difference between the two in this example, except one is uglier than the other ;p )

var table = new DataTable();

table.RowDeleting += (sender, e) => {
     Console.WriteLine("Deleting");
};
table.Clear();
table.Columns.Add("Foo");
table.Columns.Add("Bar");

var row = table.NewRow();
row["Foo"] = "Hello";
row["Bar"] = "World";
table.Rows.Add(row);

table.Dispose(); // "Dispose call! We've got a Dispose call here!"

row.Delete(); // "See? No one cares."

I don't know what constitutes as authoritative enough for production code, but there you go.

Community
  • 1
  • 1
moribvndvs
  • 42,191
  • 11
  • 135
  • 149
  • 1
    Fascinating, thank you. You identified a dependency between `DataRows` and the parent `DataTable`. That's enough for me to step back and say *"you know what, we need to deep copy those rows so there's no dependency*. Even though your investigations demonstrate things would work fine in my case, there's no guarantee MS won't update the framework in the future and break that undocumented behavior. Thanks again for a good constructive answer. – misha256 Jun 22 '15 at 03:44
  • @misha256 If they changed it, it'd be a rather significant breaking change to that feature. This design also hasn't changed for a very long time (if ever), so I'd say it's rather stable. You're free to do what you want, of course, but I wouldn't bother. – moribvndvs Jun 22 '15 at 03:50
-2

the data table will never get garbage collected. Dotnet will compile your code to keep that grid until the array is no longer referencing said row. The typical scenario I have seen is that until the parent object that created the grid and the array gets disposed of, the grid will stay around in the process marked for deletion but never garbage collected because it has a pending reference.

In other words, avoid doing it because typically it won't properly garbage collect the grid until the app is closed.

If it is unmanaged code it should blow up on first reference after dispose.

vermyx
  • 29
  • 4