Destructor, Deconstructor, Destructuring: We need to talk
-
Did you know there are Deconstructors in C#? Did you know they were called that?
class Rectangle
{
public readonly float Width, Height;public Rectangle (float width, float height) { Width = width; Height = height; } // 1. THIS IS A DESTRUCTOR public ~Rectangle(){ // code runs when there are no longer any references to the object Console.WriteLine("In destructor..."); } // 2. Adding this method (a DECONSTRUCTOR) provides DESTRUCTURING (but it's called a Deconstructor in C#) public void Deconstruct (out float width, out float height) { width = Width; height = Height; }
}
Here's a driver for the code:
var r = new Rectangle(15, 30);
var (width, height) = r;
Console.WriteLine($"{width} : {height}"); // output 15 : 30If you don't have the deconstructor in your class and you try the destructuring you will get an error like:
C# Compiler:
(1,6): error CS8130: Cannot infer the type of implicitly-typed │ │ deconstruction variable 'width'.
And, here is an example of Destructuring in JavaScript...
const person = {
firstName: "John",
lastName: "Doe",
age: 50
};// Destructuring
let {firstName, lastName} = person;console.log(firstName); //displays John
consol.log(lastName); // displays DoeFYI - The Rectangle example with the Deconstructor is from chapter 3 of C# 12 in a Nutshell: The Definitive Reference[
-
Did you know there are Deconstructors in C#? Did you know they were called that?
class Rectangle
{
public readonly float Width, Height;public Rectangle (float width, float height) { Width = width; Height = height; } // 1. THIS IS A DESTRUCTOR public ~Rectangle(){ // code runs when there are no longer any references to the object Console.WriteLine("In destructor..."); } // 2. Adding this method (a DECONSTRUCTOR) provides DESTRUCTURING (but it's called a Deconstructor in C#) public void Deconstruct (out float width, out float height) { width = Width; height = Height; }
}
Here's a driver for the code:
var r = new Rectangle(15, 30);
var (width, height) = r;
Console.WriteLine($"{width} : {height}"); // output 15 : 30If you don't have the deconstructor in your class and you try the destructuring you will get an error like:
C# Compiler:
(1,6): error CS8130: Cannot infer the type of implicitly-typed │ │ deconstruction variable 'width'.
And, here is an example of Destructuring in JavaScript...
const person = {
firstName: "John",
lastName: "Doe",
age: 50
};// Destructuring
let {firstName, lastName} = person;console.log(firstName); //displays John
consol.log(lastName); // displays DoeFYI - The Rectangle example with the Deconstructor is from chapter 3 of C# 12 in a Nutshell: The Definitive Reference[
never had an opportunity to develop in C#, but I'm not dead yet. In the past, I seem to recall that one of the "C# is better than C or C++" is automatic deconstruction or memory management. What did I miss?
Charlie Gilley “Microsoft is the virus..." "the problem with socialism is that eventually you run out of other people's money"
-
Did you know there are Deconstructors in C#? Did you know they were called that?
class Rectangle
{
public readonly float Width, Height;public Rectangle (float width, float height) { Width = width; Height = height; } // 1. THIS IS A DESTRUCTOR public ~Rectangle(){ // code runs when there are no longer any references to the object Console.WriteLine("In destructor..."); } // 2. Adding this method (a DECONSTRUCTOR) provides DESTRUCTURING (but it's called a Deconstructor in C#) public void Deconstruct (out float width, out float height) { width = Width; height = Height; }
}
Here's a driver for the code:
var r = new Rectangle(15, 30);
var (width, height) = r;
Console.WriteLine($"{width} : {height}"); // output 15 : 30If you don't have the deconstructor in your class and you try the destructuring you will get an error like:
C# Compiler:
(1,6): error CS8130: Cannot infer the type of implicitly-typed │ │ deconstruction variable 'width'.
And, here is an example of Destructuring in JavaScript...
const person = {
firstName: "John",
lastName: "Doe",
age: 50
};// Destructuring
let {firstName, lastName} = person;console.log(firstName); //displays John
consol.log(lastName); // displays DoeFYI - The Rectangle example with the Deconstructor is from chapter 3 of C# 12 in a Nutshell: The Definitive Reference[
raddevus wrote:
Did you know there are Deconstructors in C#?
Yes, ever since I read the first spec back in 1999. Never had a use for one though.
-
raddevus wrote:
Did you know there are Deconstructors in C#?
Yes, ever since I read the first spec back in 1999. Never had a use for one though.
EDIT (NOTE): I'm leaving the note below (I was going to delete it.) I saw some people saying, "Oh, you could use the Deconstruct method back in C# 1.0" in some StackOverflow answers. That is odd to me. Everything else I searched would reveal the C# 7.0 usage and nothing further back. So, you may be entirely correct. And, you may have had a very deep understanding of this Deconstructor Pattern. I never had heard about it before C# 7.0 & modern JavaScript use of destructuring. FYI - I even asked Copilot about it and Copilot has no knowledge of it before C# 7.0 & everything it talks about refernces C# 7.0. I even tried just finding the "Deconstructor Pattern" Anyways, you may be correct and the Internet is revising it so we forget about the old truths. It's crazy. Hope you find this discussion interesting.
raddevus wrote:Did you know there are Deconstructors in C#?
PIEBALDconsult wrote:
ever since I read the first spec back in 1999.
Well, errr... looks like you got caught on the word too. You may have read about destructors back in 1999, but you didn't read about deconstructors in 1999. Deconstructors were just added in C# 7.0: Here's a snippet from "when things were added" section in C# 12 In a Nutshell:
C# Nutshell
C# 7 introduced the deconstruction syntax for tuples (or any type with a Deconstruct method). C# 10 takes this syntax further, letting you mix assignment and declaration in the same deconstruction
This is my point. The terms are so close they muddle up everything. I also went back through my O'Reilly online bookshelf and examined the each C# In A Nutshell book (from C# 5 on...) Deconstructor is not mentioned until --
Quote:
C# 7.0 In A Nutshell
:
Deconstructors C# 7 introduces the deconstructor pattern. Whereas a constructor typically takes a set of values (as parameters) and assigns them to fields, a deconstructor does the reverse and assigns fields back to a set of variables.
-
never had an opportunity to develop in C#, but I'm not dead yet. In the past, I seem to recall that one of the "C# is better than C or C++" is automatic deconstruction or memory management. What did I miss?
Charlie Gilley “Microsoft is the virus..." "the problem with socialism is that eventually you run out of other people's money"
Generally in C++ you had a constructor to build the object. But then your object may have allocated memory for something it needed. In that case it was necessary to deallocate memory when the object went off the stack. In such a case you could write a destructor which had syntax exactly like constructor but included a prefixed ~ (tilde).
public ~Rectangle(){}
That insured that when the object is no longer referenced the code in the destructor would run automatically. Also, in C++ the destructor ran "deterministically" -- when you set your object ref to null. In C# it runs non-deterministically (whenever system or .NET CLR says memory needs cleaned). In C# they followed this pattern so that if you had a file open or some other resource you could insure that the code to close the file would run when the object no longer had a reference. Of course, C# manages memory (via GarbageCollector -GC) and so the destructor only runs once the GC runs collect() method. You can 1. set the object ref to null 2. call (global) GC.Collect() manually but not reccommended in production code And you'll see the destructor run in C#. Destructors are obviously used less in the C# world than in C++ world.
-
EDIT (NOTE): I'm leaving the note below (I was going to delete it.) I saw some people saying, "Oh, you could use the Deconstruct method back in C# 1.0" in some StackOverflow answers. That is odd to me. Everything else I searched would reveal the C# 7.0 usage and nothing further back. So, you may be entirely correct. And, you may have had a very deep understanding of this Deconstructor Pattern. I never had heard about it before C# 7.0 & modern JavaScript use of destructuring. FYI - I even asked Copilot about it and Copilot has no knowledge of it before C# 7.0 & everything it talks about refernces C# 7.0. I even tried just finding the "Deconstructor Pattern" Anyways, you may be correct and the Internet is revising it so we forget about the old truths. It's crazy. Hope you find this discussion interesting.
raddevus wrote:Did you know there are Deconstructors in C#?
PIEBALDconsult wrote:
ever since I read the first spec back in 1999.
Well, errr... looks like you got caught on the word too. You may have read about destructors back in 1999, but you didn't read about deconstructors in 1999. Deconstructors were just added in C# 7.0: Here's a snippet from "when things were added" section in C# 12 In a Nutshell:
C# Nutshell
C# 7 introduced the deconstruction syntax for tuples (or any type with a Deconstruct method). C# 10 takes this syntax further, letting you mix assignment and declaration in the same deconstruction
This is my point. The terms are so close they muddle up everything. I also went back through my O'Reilly online bookshelf and examined the each C# In A Nutshell book (from C# 5 on...) Deconstructor is not mentioned until --
Quote:
C# 7.0 In A Nutshell
:
Deconstructors C# 7 introduces the deconstructor pattern. Whereas a constructor typically takes a set of values (as parameters) and assigns them to fields, a deconstructor does the reverse and assigns fields back to a set of variables.
Oh! That! OK, yes, -- mea culpa -- I misread and didn't make the connection to Tuples. I try not to use new C# features, so I've been using (one or two) features of v7 (and v6) for only a few months now. Marc Clifton pointed out something about them earlier this month -- The Lounge[^] -- and I quickly ran into an error, something along the lines of : "No Deconstruct method found for type ..." (maybe I'll try to reproduce the error later, but I probably won't). My reaction is to avoid using that feature if it means additional invisible method calls which can easily be avoided by other techniques. I still prefer avoiding using tuples in favor of custom classes in most cases. In fact, after Marc's post, I decided to review my uses of Tuples in code I've written over the past few months and found that I wasn't using any -- I thought I was using Tuples in two particular situation, but I had already switched to a classes. For the most part, I use a Tuple as a "that's good enough for now, I'll fix it later" technique. But if I used Tuples more, I would probably use that feature and maybe, that feature will make Tuples more palatable in situations in which I might use a Tuple. I'll also add, that it's a case in which the Method being called has to be written for it and then the caller has to abide by it. From what I can tell, in a case in which you're calling a third-party API, the caller has no say in whether or not to use the technique.
-
Generally in C++ you had a constructor to build the object. But then your object may have allocated memory for something it needed. In that case it was necessary to deallocate memory when the object went off the stack. In such a case you could write a destructor which had syntax exactly like constructor but included a prefixed ~ (tilde).
public ~Rectangle(){}
That insured that when the object is no longer referenced the code in the destructor would run automatically. Also, in C++ the destructor ran "deterministically" -- when you set your object ref to null. In C# it runs non-deterministically (whenever system or .NET CLR says memory needs cleaned). In C# they followed this pattern so that if you had a file open or some other resource you could insure that the code to close the file would run when the object no longer had a reference. Of course, C# manages memory (via GarbageCollector -GC) and so the destructor only runs once the GC runs collect() method. You can 1. set the object ref to null 2. call (global) GC.Collect() manually but not reccommended in production code And you'll see the destructor run in C#. Destructors are obviously used less in the C# world than in C++ world.
-
EDIT (NOTE): I'm leaving the note below (I was going to delete it.) I saw some people saying, "Oh, you could use the Deconstruct method back in C# 1.0" in some StackOverflow answers. That is odd to me. Everything else I searched would reveal the C# 7.0 usage and nothing further back. So, you may be entirely correct. And, you may have had a very deep understanding of this Deconstructor Pattern. I never had heard about it before C# 7.0 & modern JavaScript use of destructuring. FYI - I even asked Copilot about it and Copilot has no knowledge of it before C# 7.0 & everything it talks about refernces C# 7.0. I even tried just finding the "Deconstructor Pattern" Anyways, you may be correct and the Internet is revising it so we forget about the old truths. It's crazy. Hope you find this discussion interesting.
raddevus wrote:Did you know there are Deconstructors in C#?
PIEBALDconsult wrote:
ever since I read the first spec back in 1999.
Well, errr... looks like you got caught on the word too. You may have read about destructors back in 1999, but you didn't read about deconstructors in 1999. Deconstructors were just added in C# 7.0: Here's a snippet from "when things were added" section in C# 12 In a Nutshell:
C# Nutshell
C# 7 introduced the deconstruction syntax for tuples (or any type with a Deconstruct method). C# 10 takes this syntax further, letting you mix assignment and declaration in the same deconstruction
This is my point. The terms are so close they muddle up everything. I also went back through my O'Reilly online bookshelf and examined the each C# In A Nutshell book (from C# 5 on...) Deconstructor is not mentioned until --
Quote:
C# 7.0 In A Nutshell
:
Deconstructors C# 7 introduces the deconstructor pattern. Whereas a constructor typically takes a set of values (as parameters) and assigns them to fields, a deconstructor does the reverse and assigns fields back to a set of variables.
Thanks MS. My summary of this discussion is that it should not be this complicated. Any system - compiler or otherwise - should have well defined behavior. Leaving ANYTHING to Microsoft to determine "well defined behavior" is a recipe for disaster.
Charlie Gilley “Microsoft is the virus..." "the problem with socialism is that eventually you run out of other people's money"
-
Did you know there are Deconstructors in C#? Did you know they were called that?
class Rectangle
{
public readonly float Width, Height;public Rectangle (float width, float height) { Width = width; Height = height; } // 1. THIS IS A DESTRUCTOR public ~Rectangle(){ // code runs when there are no longer any references to the object Console.WriteLine("In destructor..."); } // 2. Adding this method (a DECONSTRUCTOR) provides DESTRUCTURING (but it's called a Deconstructor in C#) public void Deconstruct (out float width, out float height) { width = Width; height = Height; }
}
Here's a driver for the code:
var r = new Rectangle(15, 30);
var (width, height) = r;
Console.WriteLine($"{width} : {height}"); // output 15 : 30If you don't have the deconstructor in your class and you try the destructuring you will get an error like:
C# Compiler:
(1,6): error CS8130: Cannot infer the type of implicitly-typed │ │ deconstruction variable 'width'.
And, here is an example of Destructuring in JavaScript...
const person = {
firstName: "John",
lastName: "Doe",
age: 50
};// Destructuring
let {firstName, lastName} = person;console.log(firstName); //displays John
consol.log(lastName); // displays DoeFYI - The Rectangle example with the Deconstructor is from chapter 3 of C# 12 in a Nutshell: The Definitive Reference[
Looking at this article Deconstructing tuples and other types - C# | Microsoft Learn[^] I see that Deconstructor is not related to constructor, destructor and finalizer. In the context of .NET instance lifetime, this is just misleading method name.
-
Did you know there are Deconstructors in C#? Did you know they were called that?
class Rectangle
{
public readonly float Width, Height;public Rectangle (float width, float height) { Width = width; Height = height; } // 1. THIS IS A DESTRUCTOR public ~Rectangle(){ // code runs when there are no longer any references to the object Console.WriteLine("In destructor..."); } // 2. Adding this method (a DECONSTRUCTOR) provides DESTRUCTURING (but it's called a Deconstructor in C#) public void Deconstruct (out float width, out float height) { width = Width; height = Height; }
}
Here's a driver for the code:
var r = new Rectangle(15, 30);
var (width, height) = r;
Console.WriteLine($"{width} : {height}"); // output 15 : 30If you don't have the deconstructor in your class and you try the destructuring you will get an error like:
C# Compiler:
(1,6): error CS8130: Cannot infer the type of implicitly-typed │ │ deconstruction variable 'width'.
And, here is an example of Destructuring in JavaScript...
const person = {
firstName: "John",
lastName: "Doe",
age: 50
};// Destructuring
let {firstName, lastName} = person;console.log(firstName); //displays John
consol.log(lastName); // displays DoeFYI - The Rectangle example with the Deconstructor is from chapter 3 of C# 12 in a Nutshell: The Definitive Reference[
Purely from an english language perspective, to me:
destructor
is something that destroys, i.e. smashes, obliterates...deconstructor
deconstructs, i.e. disassembles, takes apart, leaving the components presumably intact and usabledestructuring
sounds like something politicians do (or talk about).Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
-
Did you know there are Deconstructors in C#? Did you know they were called that?
class Rectangle
{
public readonly float Width, Height;public Rectangle (float width, float height) { Width = width; Height = height; } // 1. THIS IS A DESTRUCTOR public ~Rectangle(){ // code runs when there are no longer any references to the object Console.WriteLine("In destructor..."); } // 2. Adding this method (a DECONSTRUCTOR) provides DESTRUCTURING (but it's called a Deconstructor in C#) public void Deconstruct (out float width, out float height) { width = Width; height = Height; }
}
Here's a driver for the code:
var r = new Rectangle(15, 30);
var (width, height) = r;
Console.WriteLine($"{width} : {height}"); // output 15 : 30If you don't have the deconstructor in your class and you try the destructuring you will get an error like:
C# Compiler:
(1,6): error CS8130: Cannot infer the type of implicitly-typed │ │ deconstruction variable 'width'.
And, here is an example of Destructuring in JavaScript...
const person = {
firstName: "John",
lastName: "Doe",
age: 50
};// Destructuring
let {firstName, lastName} = person;console.log(firstName); //displays John
consol.log(lastName); // displays DoeFYI - The Rectangle example with the Deconstructor is from chapter 3 of C# 12 in a Nutshell: The Definitive Reference[
raddevus wrote:
If you don't have the deconstructor in your class and you try the destructuring you will get an error
Unless you have a deconstructor extension method, which can be handy for third-party classes that don't provide them:
// In your "SimpleShapes.dll" assembly:
public class Rectangle(float width, float height)
{
public readonly float Width = width, Height = height;
}// In my application code:
public static class Shapes
{
public static void Deconstruct (this Rectangle rectangle, out float width, out float height)
=> (width, height) = (rectangle.Width, rectangle.Height);
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer