he's in the right forum, he's clearly using C++/CLI and not native C++.
iddqd515
Posts
-
Write to Access Database using C++ and OleDB connection -
Forward Declaration and no appropriate default constructoryeah that's exactly the problem. Alternatively you could call Foo(arr). The C# compiler properly recognizes that an array is System::Array so it doesn't require that cast. I don't believe there's any way to dynamically get the generic type argument with typeof or GetType(). It seems this would make it quite difficult to use generics dynamically based on user input or something similar.
-
Forward Declaration and no appropriate default constructorInteresting stuff, but I'm not sure its quite along the lines I'm looking for. Do you have a code example or solution that demonstrates the problem where the compiler doesn't recognize the proper base class of the derived class and just thinks its a System::Object?
-
Forward Declaration and no appropriate default constructorI forgot to read what I posted. I meant a function with an argument of the generic interface IEnumerable^ not IEnumerable^. That's what prompted me to connect your problem with that bug. I'm about to try fiddling with it.
-
Forward Declaration and no appropriate default constructorThat's interesting. There's a bug where the C++/CLI compiler won't recognize that a managed array implements System::Array. The result is you can't pass a managed array to a function that takes an argument as IEnumerable^ or something similar. What you're saying makes it sound like this bug might just be a more specific case of a general problem the C++/CLI compiler has with generics. Unless I'm misunderstanding you.
-
What makes a class IDisposable?Yeah its taken me over a month to really grasp the whole pattern and how it meshes with traditional C++ semantics. Its not helpful when you try to find stuff about the Dispose pattern and end up with C# examples mixing terms to create more confusion. On the plus side, now C++/CLI basically works just like you would expect native C++ to in most cases and you only need to worry about finalizers for classes with unmanaged members. Certainly an improvement over MC++ (as most things are).
-
What makes a class IDisposable?Sorry, I was being ambiguous. All this Dispose talk and switching between C# and C++/CLI gets me mixed up occasionally. You're correct, I meant in the destructor a call to
Dispose(true)
is made. In any case, the important part (C++/CLI destructors are deterministic) is the same, while a C# finalizer is completely different due to its nondeterministic nature. Luckily I've never had to use MC++. *shudder* -- modified at 15:49 Monday 13th August, 2007 -
What makes a class IDisposable?So that right there says 'sorry we incorrectly used to refer to this as a destructor. We realized it was confusing because its really not a destructor at all. To get destructor like behavior in C# use the Dispose method.' Therefore, C# has no destructors. And even in the past, it only had them in name, not function. But its been awhile since anyone referred to them as destructors since its blatantly confusing, especially with the introduction of C++/CLI in '05.
-
What makes a class IDisposable?Well like I said then, make sure to declare
~Class()
in all your C# classes and don't bother explicitly invokingDispose
. I'm sure you'll find it works fantastically. Also make sure to take advantage of finalizers to declare reference classes in C# with stack semantics. -- modified at 15:30 Monday 13th August, 2007 -
What makes a class IDisposable?From: http://en.wikipedia.org/wiki/Destructor\_(computer\_science) In object-oriented programming, a destructor (sometimes shortened to dtor) is a method which is automatically invoked when the object is destroyed. Its main purpose is to clean up and to free the resources which were acquired by the object along its life cycle and unlink it from other objects or resources invalidating any references in the process. The use of destructors is key to the concept of RAII. How in C# do you declare such a thing? A finalizer is not automatically invoked when the object is destroyed deterministically. It is nondeterministically called by the GC at some point in the future. Most important, in no way does a finalizer enable the RAII pattern. Take a
FileStream
class which encapsulates a resource in C#. Declare a finalizer for it. When an instance of a FileStream class goes out of the scope the finalizer is not called then. You do not know when it is called. Furthermore, even if the GC does a collect and there are no roots in the code to the object, the simple existence of the finalizer counts as a root and can cause theFileStream
object to be promoted into the next generation and not collected by the GC until the next collect cycle (who knows when that will be). So while yourFileStream
object may have gone out of scope ages ago, by not callingDispose
and assuming the finalizer will close theFileStream
, you have potentially caused a resource leak. The next function call that assumes the file you previously had used with theFileStream
object is closed may throw an exception because you were relying on the garbage collector to nondeterministically release a critical resource. On the other hand, a destructor in C++/CLI will be called the moment theFileStream
goes out of scope (assuming you declared the object with stack semantics and notgcnew
). Then in the destructor you make sure there is a call toDispose
and you ensure that the resource is released immediately. You don't need atry/finally
and you don't need to explicitly callDispose
and nor does anyone who uses your class in the future. The destructor incurs no performance penalty during allocation or deallocation like a finalizer does either. There's no way to declare such a function in C#. To say 'I'm not repudiating the mechanics' therefore C# has destructors is completely wrong. The mechanics are exa -
What makes a class IDisposable?I'm pretty sure we've said the same thing. However... You say destructors are not called on an object allocated on the managed heap which isn't strictly true. If you allocate it on the managed heap with
gcnew
then yes the destructor is never called if you don't manually calldelete
. However, if you instantiate theref class
object with stack semantics then the destructor is called implicitly when the object goes out of scope (even though underneath its still allocated on the managed heap like allref class
objects). This is the critical addition to C++/CLI (vs MC++) that allowed for RAII style coding like native C++. Michael was claiming this is not the case (as it is in native C++) and that the finalizer is what is called, which is not correct. The finalizer will be called eventually either way if you define one, but the way things work is obviously much different than what a destructor provides. The confusion is that in C# when you declare~Class1()
this is actually mapped to the finalizer (Dispose(false)
) in the dispose pattern. C# has no concept of destructors like C++ or C++/CLI even though the semantics there look like you're declaring a destructor. In C++/CLI you accomplish the same thing by declaring!Class1()
which more properly distinguishes the finalizer from the destructor. Then declaring ~Class1() in C++/CLI does a very different thing than~Class1()
in C#. That's why in C# you need to explicitly callDispose()
in afinally
block or use ausing
block with things likeFileWriter
objects to ensure there is no resource leak. C++/CLI's destructor semantics provide the handy native C++ style,FileWriter fw;
which will automatically be disposed of properly when it goes out of scope (deterministically). -
What makes a class IDisposable?You seem to be confused. You have to be concerned with what goes on underneath or you won't understand how this works. When you write
~Class1()
in C# you have a finalizer in behavior. The syntax is like a C++ destructor and this is confusing on Microsoft's part. Assume you have a C# class with~Class1()
defined. Now, whenever you instantiate an object of Class1 you incur a performance penalty simply because the finalizer exists. The Class1 instance must register in a Finalizable queue and an freachable queue when the GC does its business. ~Class1() (really a call toDispose(false)
) will be invoked by the garbage collector every time an object of Class1 is about to be reclaimed. The simple existence of~Class1()
and the subsequent placement in the freachable queue can cause objects of Class1 to be promoted to another generation and not be collected by the GC when it really could be. Most importantly, you have no idea when~Class1()
will be called by the garbage collector. Its completely nondeterministic. This by its very nature means its not a destructor. The finalizer is there to let you code last minute cleanup of unmanaged resources (which the GC cannot work with) in case the user of your class did not properly callDispose()
on an instance of Class1 or use ausing
block. And like I said before, there's a huge number of restrictions for what you can do in a finalizer vs a destructor. Now assume we have Class1 in C++/CLI with~Class1()
defined. This will be called when an object of Class1 goes out of scope IF you declared that object with stack semantics (i.e.,Class1 myClass1Object
). If you dynamically allocate memory withgcnew
then you must usedelete
to invoke the destructor deterministically. This is the same as what happens in native C++. The difference in C++/CLI is that the memory itself won't be immediately reclaimed immediately (as that's the GC's job and it works nondeterministically) but that's not an issue. It will be reclaimed when more memory is required. The important part is that the destructor (~Class1()
) will always be invoked implicitly when the automatic variable goes out of scope. A C# class with~Class1()
defined does not function this way because in C#~Class1()
is a finalizer not a destructor. So in C++/CLI you put resource-release code in your destructor~Class1()
and then an automatic vari -
What makes a class IDisposable?That's just it though, it is syntactic sugar. When you write ~Class1() in C# you've got a finalizer. It's not doing something then calling
Finalize()
I don't believe. Internally the compiler synthesizes that to a call toDispose(false)
which is invoked by the garbage collector right before the memory is reclaimed nondeterministically. By contrast, a destructor in C++/CLI is synthesized toDispose() { Dispose(true); GC::SuppressFinalize(); }
While a call to !Class1() in C++/CLI (the finalizer) results in a call toDispose(false)
. The ~Class1() is a finalizer, not a destructor. To call it a destructor is a complete misnomer and doesn't convey when or how its called. A destructor would be called automatically when the object goes out of scope (via ausing
block in C# or via stack semantics in C++/CLI) or when invoked specifically byDispose()
. You must not reference other finalizable objects in that finalizer and other similar rules for finalizers that aren't present in a destructor. In C++/CLI a class destructor is created by the compiler automatically and will clean up managed resources for you. A finalizer (~Class1() in C#) is not generated by the compiler. It only exists if you explicitly write one. Most important is the fact that the ~Class1() in C# is nondeterminitic which by its nature makes it not a destructor (since they're deterministic) and the performance penalty for creating a finalizer for a class (In C++/CLI you would incur this cost with !Class1() but ~Class1() would enable actual RAII destructor semantics like native C++). In C++/CLI you would write ~Class1() to properly handle the closing of resources in a way that can be done deterministically (when the object goes out of scope or a call todelete
is made). This is a destructor. In C# when you write ~Class1() you're providing a way for the garbage collector to handle resource cleanup or unmanaged cleanup at the last second before memory reclamation in the case that the user failed to manually release it withDispose
or ausing
block. This is a finalizer. There is no destructor. You can't call delete. You have to write aDispose
method and/or useusing
blocks. The C++/CLI dtor/ctor behavior is semantically the same as native C++. Although the destructor in C++/CLI doesn't cause the memory to actually be reclaimed (as that's always the garbage collectors job for managed objects) it is invo -
What makes a class IDisposable?oh right, wasn't paying close enough attention. And yes MS semantics are horribly confusing. In that case, the C# ~Class1() is the finalizer. And by explicitly defining one you ensure that it is called by the garbage collector before the memory for an instance of the class is reclaimed. So although you're printing 'destructed' its actually the garbage collector calling the finalizer before memory is reclaimed. Its not a destructor that runs when the variable goes out of scope as you would get if it was a C++/CLI
ref class
with ~Class1() defined. And unlike destruction, finalization is nondeterministic and incurs a high performance cost for both allocation and deallocation. So you never want to write one unless your class contains unmanaged resources that won't be cleaned up by the garbage collector. In that case the finalizer will ensure the unmanaged stuff is cleaned up even if someone forgets to calldelete
orDispose
. -
What makes a class IDisposable?His post was C# specific, which is quite different from C++/CLI in some ways. In C# there is no destructor. The destructor syntax in C# ( ~Class1() ) is actually a finalizer. In C++/CLI ~Class1() maps to the Dispose() function from IDisposable giving you a form of deterministic destruction (though memory won't be reclaimed immediately you can count on resources being closed). The !Class() syntax maps to the finalizer in C++/CLI.
-
c++ projectsgood luck with that, I'm sure you won't fail to impress
-
minimizing dialog to system traybut reading is so hard :(
-
What is special about Dispose() methods?Dispose()
is a function inherited from theIDisposable
interface. Its meant to implement the "Dispose pattern" to enable some form of immediate destructors in managed code. In C# you can callDispose()
on objects that will perform some clean up functions (like closing streams and such). In C++/CLIDispose()
is mapped to the class destructor by the compiler. You can't explicitly invokeDispose()
(nor write one). Instead, if an object encapsulating a resource needs some clean up done immediately (rather than waiting for the garbage collector) call either aClose()
type function (which itself should only call the destructor I believe) or usedelete
(or declare the variable with stack semantics and have the destructor called automatically when the variable goes out of scope). -
Create a tableyou've created a rectangular multidimensional array rather than a jagged one. As such, you need to access elements like this
tab[i,j]
rather thantab[i][j]
(which you would do for a jagged array in C++/CLI) -
C++ with .NET 3.0 under VS 2005if you're going to do much WPF stuff (and especially XAML) just save yourself the headache and use C#