Thread: What's so special about c#?

  1. #16
    Registered User
    Join Date
    Aug 2008
    Posts
    188
    Quote Originally Posted by valaris View Post
    Finalize() is called when an object is being deleted. It is in effect a destructor for C#, usually it's only used to free managed resources. Its syntax is also similar to C# as in ~ClassName();.
    i think u mean to say unmanaged resources.

  2. #17
    Registered User
    Join Date
    Aug 2008
    Posts
    188
    for me personally i am way more productive with C# than i am with C++, and using the library is much more convenient/consistent than a mix/match of Win32, stdlib, or boost libraries.

    back on topic, there is no X is better than Y. there is only X is better suited for Z than Y. in general i think learning C++ first will make you a better C# programmer....

    the one thing you need to watch out for is not to think in the old language. learn to think in the new language.

    people who have seen "VB6 style" code in .NET know what i'm talking about.... :'(

  3. #18
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Plus, it helps improve performance -- if a large number of objects go out of scope at once, they don't need to all be destroyed immediately while your thread sits on its ass waiting.

    The role that destructors play in memory management is just a side-effect of their real purpose; to do *something* precisely when the object goes out of scope. For example, you may have an object that writes an XML start tag in it's constructor, and a closing tag in it's destructor, eg:

    Code:
    xml_writer a( "outermost" ), b( "middle" ), c( "innermost" );
    Obviously, for things to work properly, the objects have to be destroyed in a specific order.

    The importance and usefulness of the destructor really can't be overstated. Their absence from languages such as C# and Java is a real shame, indeed.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #19
    Registered User
    Join Date
    Aug 2008
    Posts
    188
    yes, you *could* do that with a constructor/destructor, but i'm still unconvinced from your XML example why C# lacking true deterministic deallocation is "inherently flawed."

    edit: btw, i say true deterministic deallocation because even though in C# you can manually call Dispose() on an object, technically the instance is still available in memory, unlike C++'s delete.
    Last edited by bling; 04-30-2009 at 03:55 PM.

  5. #20
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> but i'm still unconvinced from your XML example why C# lacking true deterministic deallocation is "inherently flawed."

    That was just a very simple demonstrative example. There are literally innumerable mechanisms that can be described using the constructor/destructor idiom, as they essentially model a stack (and thus recursion), arguably one of the most important concepts of computer science. The question isn't "what are they good for?" but "what can't they be used for?".
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #21
    Registered User
    Join Date
    Aug 2008
    Posts
    188
    well, if you're argument is simply to do something upon construction and destruction, rather than allocating/deallocating memory, then there really isn't much difference between C#'s IDisposable pattern vs C++'s destructor....

    actually, in C++/CLI if you declare a C++ destructor it actually compiles into a Dispose() method, which via stack semantics Dispose() will automatically be called when the object goes out of scope.

  7. #22
    Registered User
    Join Date
    Aug 2008
    Posts
    188
    i will say that *properly* implementing the IDisposable pattern in .NET is a complete pain in the butt with numerous places where you can screw up. and since it is a pattern, there is no guarantee that it will be done exactly the same across different libraries and programmers....which leads to more pain in the butt.

    here's one of the most comprehensive guides to implementing the pattern:
    Joe Duffy's Weblog
    yes...25 pages printed.

  8. #23
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507
    Quote Originally Posted by bling View Post
    i think u mean to say unmanaged resources.
    Hehe yes i did, sorry.

  9. #24
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> i will say that *properly* implementing the IDisposable pattern in .NET is a complete pain in the butt

    I don't even bother with it; I always invoke cleanup code manually. It sure would be nice if I didn't have to, though.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #25
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by bling
    well, if you're argument is simply to do something upon construction and destruction, rather than allocating/deallocating memory, then there really isn't much difference between C#'s IDisposable pattern vs C++'s destructor....
    Okay, this is confusing

    Are you saying that although the programmer can call Dispose earlier (i.e., deterministic but manual deallocation), Dispose will be invoked automatically when the object goes out of scope? My impression (from Clemens Szyperski's annotation in the article you linked to) is that if the programmer does not call Dispose, Dispose will be called sometime during finalization, in which case it is not equivalent to the deterministic destruction provided by (standard) C++ destructors.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #26
    Registered User
    Join Date
    May 2007
    Posts
    147
    ...and in a tangentially related point

    Plus, it helps improve performance -- if a large number of objects go out of scope at once, they don't need to all be destroyed immediately while your thread sits on its ass waiting.
    ...as opposed to stopping executing at ANOTHER point to do it, when you have no control on the performance hit.

    My point here is that this doesn't save time overall - the same work has to be done at some point, and if you're not in control of that then it will increase the memory footprint while those objects that are out of scope hang around.

    It's a double edged cutting issue.

    If a collection of 20,000 objects fall out of scope, how long does that take? It depends on what happens as they do. Tens of millions can be processed per second on typical hardware when the destructor is trivial, and depending on what's really going on, the net result (sometimes due to compiler optimization) can be zero work has to be done. That's almost never true on .NET; some under the hood management of the implied base object has to be managed at the minimum on a collection of such objects.
    Last edited by JVene; 05-01-2009 at 06:27 AM.

  12. #27
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I always thought that it was deterministic, but apparently not. According to MSDN:

    The primary use of this interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. However, it is not possible to predict when garbage collection will occur.
    Note the misuse of the word "automatically".

    [edit]
    I see. It's deterministic iff the object is manipulated within the "using" syntax.
    [/edit]
    Last edited by Sebastiani; 05-01-2009 at 06:29 AM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #28
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Sebastiani
    Note the misuse of the word "automatically".
    How is it misuse? It is true that the garbage collector automatically releases the memory for managed objects, since (at least ideally) the programmer does not need to manually do so.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #29
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I should have amended that in my edit. But yes, it is automatic (as long as the "using" syntax is employed, of course).
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  15. #30
    Registered User
    Join Date
    Aug 2008
    Posts
    188
    Quote Originally Posted by laserlight View Post
    Okay, this is confusing

    Are you saying that although the programmer can call Dispose earlier (i.e., deterministic but manual deallocation), Dispose will be invoked automatically when the object goes out of scope? My impression (from Clemens Szyperski's annotation in the article you linked to) is that if the programmer does not call Dispose, Dispose will be called sometime during finalization, in which case it is not equivalent to the deterministic destruction provided by (standard) C++ destructors.
    yes, very confusing indeed !! i hope Sebastiani's link from MSDN made it a little more clear.

    basically:
    a) the programmer cannot deterministically clean up managed resources
    b) IDisposable provides a pattern for cleaning up unmanaged resources (and optionally do so deterministically by calling Dispose() directly)

    anyways, IDisposable is such a complicated mess probably because .NET has to support multiple languages. for most languages, Dispose() is optional, so if you do not call it, unmanaged resources will not be freed until the GC kicks in. however, for langauges like C++, which has RAII, Dispose() will automatically called when an object goes out of scope. i believe the C++/CLI compiler will automatically generate that code even if you didn't define it.
    Last edited by bling; 05-01-2009 at 12:07 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Printing a special type?
    By blernblan in forum C Programming
    Replies: 1
    Last Post: 06-02-2009, 03:35 PM
  2. locking actions to special threads
    By pheres in forum C++ Programming
    Replies: 2
    Last Post: 09-24-2008, 10:17 AM
  3. special characters removing from srting
    By cnu_sree in forum C Programming
    Replies: 5
    Last Post: 06-06-2007, 08:30 PM
  4. special function detection
    By zyd in forum C Programming
    Replies: 7
    Last Post: 02-28-2006, 03:25 PM
  5. Special (non) Keyboard Characters
    By TechWins in forum C++ Programming
    Replies: 3
    Last Post: 05-01-2002, 12:08 AM

Tags for this Thread