locked
Is this a genuine language weakness?

    Question

  • I am unhappy that C# has continued the tradition it inherited from C++ and C, of allowing a functions return value to be ignored by allowing callers to invoke functions as if they were methods. I think this is poor programming practice personally, C# enforces many sensible things but not this.

    A good case in point is if I invoke a function that returns me a disposable object but ignore (never refer to) the returned object reference.

    The method will create or obtain this object and return a reference to it, yet because it is ignored the caller will never call its Dispose method and so the object will have to be diposed of by the system, asynchronoulsy by the GC (unless it is disposed by some other thread or some other code).

    If the system's runtime was aware that a disposable object reference was returned but never assigned, I guess it could automatically call Dispose silently which would not be an invalid thing to do under the circumstances.

    But this is not trivial, because the functions return value could be implicitly used:

    SomeFunc(arg).SomeObjMethod(other_arg);

    Here the object ref returned by 'SomeFunc' is used but never retained, so we cannot dispose it, however it is used transiently to invoke 'SomeObjMethod' so cannot be automatically 'disposed' unless this is done after the completion of the entire statement...

    What do others think about this issue?

    Thanks

    Cap'n

     

     

    Sunday, October 03, 2010 6:20 PM

Answers

  • I do not see this as a weakness.  It is an inherent design decision.

     

    Without this feature, it would be impossible to design fluent interfaces.  Language features like LINQ would not be possible, and most functional style programming would be impossible.

     

    For example, allowing this is what makes writing statements like:

     

        var results = myCollection.Where(item => item.MyProperty > 3).Select(item => new {Name = item.Name, Value = item.MyProperty + item.MyProperty2 }).Take(10);

     

    Here, you have many references which are used but not retained.  This provides a huge amount of flexibility and functionality - I would not want to use a language that forced you to retain every result, as it would dramatically reduce productivity.


    Reed Copsey, Jr. - http://reedcopsey.com
    Sunday, October 03, 2010 6:38 PM
    Moderator
  • I do think that the compiler (or Code Analysis) could warn you if you fail to assign an IDisposable return value to something (or use a "using"). That would give you lots of false positives, though, when a method returns something IDisposable which wasn't created by the method and therefore shouldn't necessarily be disposed by the caller.

    I've taken to returning IDisposable things via an "out" parameter to ensure that the user does something with them.

    What I would love to see is a compiler-enforced attribute that you could put onto methods that stated that calling code MUST do something with the return value. You would apply that attribute to your methods that create the IDisposable thing being returned.

    Monday, October 04, 2010 1:20 PM
  • The Optimizing compiler is pretty clever.  I would not be surprised to learn that this scenario has been foreseen and accounted for in a most efficient manner.  GC marks objects---with a 0, 1, or 2---as they are processed.  I would not be surprised that these orphaned return objects skip the '0' phase and are marked immediately for phase '1' or '2'.

    I always do something with return objects, anyway.  I was taught that not doing so was bad form.  It was explained to me like this.   "Don't leave them hanging out there for the elves to clean up.  Someday the elves might change their work habits, which might cause some potentially big problems." 

    In other words, you code is relying on unofficially documented run time behaviors that could change without notice.  Granted, some changes are more, or less, likely to occur than others.  I think this behavior is very much in the unlikely camp.

    Rudy   =8^D


    Mark the best replies as answers. "Fooling computers since 1971."

    http://rudedog2.spaces.live.com/default.aspx

    Monday, October 04, 2010 5:20 PM
    Moderator
  • What? You think that it's not critical to dispose things that are supposed to be disposed? Crikey!

     

    Not as you handle a method which is meant to release unmanaged resources and his Idisposable interface as a method which disposes objects.

    Because that your father and mother have given you the name Matthew, does it not mean that everything you do is the same for all who have the name Matthew. 

    The same for the method name Dispose and the interface IDisposable, it is just a method name.

    Disposing of objects is done by the GC.


    Success
    Cor
    Tuesday, October 05, 2010 9:37 AM
  • because we could code void methods that use ref arguments for those cases where the value wasn't always needed and actually return a value where we wanted to insist the caller use the returned value.

    Actually it's the opposite. Having a byref parameter forces the caller to provide a variable to hold the returned value. You cannot ignore a byref parameter.
    Tuesday, October 05, 2010 10:24 AM
  • What? You think that it's not critical to dispose things that are supposed to be disposed? Crikey!

     

    Not as you handle a method which is meant to release unmanaged resources and his Idisposable interface as a method which disposes objects.

    Because that your father and mother have given you the name Matthew, does it not mean that everything you do is the same for all who have the name Matthew. 

    The same for the method name Dispose and the interface IDisposable, it is just a method name.

    Disposing of objects is done by the GC.


    Success
    Cor

    Disposing of unmanaged resources *may* be done by the GC, *if* someone implemented a finalize method. But such a finalizer will not be allowed to touch any managed resources.

    If one of the resources is critical, you'll be in a world of pain if you don't dispose it in a timely manner, especially if some other code wants to access the same resource shortly afterwards.

    I repeat my previous question; please have a go at answering it:

    What do you think this code will do?

    using System;
    using System.IO;

    public class Demo
    {
      public static void Main()
      {
        File.CreateText("C:\\TEST\\TEST.TXT");
        File.CreateText("C:\\TEST\\TEST.TXT");
      }
    }

    Seriously, you need to wise up about this kind of problem. There are many examples of people getting into trouble because they didn't dispose something. Here's a recent one:

    http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/72df3a7c-8b96-4e84-a9a6-6856f1b9f4d4

     

    Tuesday, October 05, 2010 2:55 PM
  • > allowing a functions return value to be ignored by allowing callers

    Suppoes the method returns an object and the compiler forces you to make use of the result.  Suppose the returned object has 4 properties, one of which is "really important".  Suppose the caller gets the value of 3 of the 4 properties, but not the "really important" one.  So your feature does not buy you much: the caller can still ignore something "important".

    Java has something similar where a method can declare that it can throw a so-called "checked" type of exception.  This forces the caller to catch or rethrow exceptions of that type.  The .NET architects considered and rejected this approach.  There seem to be no perfect solutions, only tradeoffs.

    > I guess it could automatically call Dispose silently which would not be an invalid thing to do under the circumstances.

    Actually, it might be invalid.  The method you called may have established a path between a surviving GC root and the returned object.  For example, in addition to returning the object it might have also added it to a cache.  The compiler cannot know this has happened in general.

     


    The usual response to this kind of comment is "There is no greater fool than he who did nothing because he could do so little." Or alternatively "Suppose my brother was a girl. Then he'd be my sister!". :)

    Yes, you have to work to ensure that the caller at least does something with a returned value. The problem was so bad with C/C++ functions returning error values that they invented exceptions to deal with the problem!

    One solution, as I outlined above, is to use 'out' parameters for things that must not be ignored. (The only things that normally must not be ignored are error messages - now handled with exceptions - and things that must be disposed.)

    What we do is for the DEBUG (not release) versions of a finalizer (or Dispose(bool) called with a false value) for a class that MUST be disposed is to display a message box complaining about the fact that Dispose() wasn't called.

    Two examples of our classes that MUST be disposed are:

    (1) A class that represents a floating license acquired to enable the user to run some function in our software. If that license was not released, it means another user could not use it until the garbage collector runs.

    (2) A class that encapsulates a lock on a database record, preventing other users from editing it.

    The code that we use to display the error message looks like this. Note the code that prevents the message box being displayed if we're running a unit test (for obvious reasons):

    protected override void Dispose(bool disposing)
    {
      if (!_isDisposed)
      {
        if (disposing)
        {
          _isDisposed = true;
          // Rest of normal dispose logic here.
        }
        else // Called from finalizer because nobody called Dispose().
        {
          #if DEBUG  // Don't laden the release version with this.
    
          string message = this.GetType().FullName + " wasn't disposed properly.";
          Debug.WriteLine(message);
    
          bool isRunningUnitTest = (Process.GetCurrentProcess().ProcessName == "VSTestHost");
    
          if (Environment.UserInteractive && !isRunningUnitTest)
          {
            MessageBox.Show   // Disposing this properly is important enough to display an error message!
            (          // Otherwise some streams will be left open, which would be a bad thing...
              message,
              Application.ProductName + " - Diagnostic",
              MessageBoxButtons.OK,
              MessageBoxIcon.Information,
              MessageBoxDefaultButton.Button1,
              MessageBoxOptions.DefaultDesktopOnly // This prevents the message from disappearing as the process closes.
            );
          }
    
          #endif
        }
      }
    }
    
    
    It will always be necessary to include such diagnostics I think, because you can never force callers to dispose things. All you can do is mitigate things (ideally through the use of special attributes that you can apply to factory methods, for example, but for now "out" parameters will have to do).

     

    Wednesday, October 06, 2010 9:04 AM

All replies

  • I do not see this as a weakness.  It is an inherent design decision.

     

    Without this feature, it would be impossible to design fluent interfaces.  Language features like LINQ would not be possible, and most functional style programming would be impossible.

     

    For example, allowing this is what makes writing statements like:

     

        var results = myCollection.Where(item => item.MyProperty > 3).Select(item => new {Name = item.Name, Value = item.MyProperty + item.MyProperty2 }).Take(10);

     

    Here, you have many references which are used but not retained.  This provides a huge amount of flexibility and functionality - I would not want to use a language that forced you to retain every result, as it would dramatically reduce productivity.


    Reed Copsey, Jr. - http://reedcopsey.com
    Sunday, October 03, 2010 6:38 PM
    Moderator
  • I do think that the compiler (or Code Analysis) could warn you if you fail to assign an IDisposable return value to something (or use a "using"). That would give you lots of false positives, though, when a method returns something IDisposable which wasn't created by the method and therefore shouldn't necessarily be disposed by the caller.

    I've taken to returning IDisposable things via an "out" parameter to ensure that the user does something with them.

    What I would love to see is a compiler-enforced attribute that you could put onto methods that stated that calling code MUST do something with the return value. You would apply that attribute to your methods that create the IDisposable thing being returned.

    Monday, October 04, 2010 1:20 PM
  • I'm not aware of any modern language which forces you to assign the return value, so it's not just the C/C++ tradition.
    Convert between VB, C#, C++, & Java (http://www.tangiblesoftwaresolutions.com)
    Monday, October 04, 2010 2:46 PM
  • The Optimizing compiler is pretty clever.  I would not be surprised to learn that this scenario has been foreseen and accounted for in a most efficient manner.  GC marks objects---with a 0, 1, or 2---as they are processed.  I would not be surprised that these orphaned return objects skip the '0' phase and are marked immediately for phase '1' or '2'.

    I always do something with return objects, anyway.  I was taught that not doing so was bad form.  It was explained to me like this.   "Don't leave them hanging out there for the elves to clean up.  Someday the elves might change their work habits, which might cause some potentially big problems." 

    In other words, you code is relying on unofficially documented run time behaviors that could change without notice.  Granted, some changes are more, or less, likely to occur than others.  I think this behavior is very much in the unlikely camp.

    Rudy   =8^D


    Mark the best replies as answers. "Fooling computers since 1971."

    http://rudedog2.spaces.live.com/default.aspx

    Monday, October 04, 2010 5:20 PM
    Moderator
  • The return value of a function sometimes is not too important.
    For example think of a function that removes an element of a list/collection
    or whatsoever which also returns the removed element such as
    XmlNode.RemoveChild does.
    Probably in 9 of 10 cases you won't need the returned element.
    The return value is a goodie here. The method's core task is to
    remove child from the nodes childList.
    Another common example would be MessageBox.Show whose
    return value isn't to important if the box only exposes an OK-button.

    Forcing the caller to retain a reference which then is never used
    would be even worse language design, producing code-bloat and
    lots of unused, un-gc-able objects.
    So it is actually good and effective that we programmers decide
    which return values are of interest.

    Concerning the IDisposable-argument.
    Returning an IDisposable and not retaining it
    markes the object as 'targeted for GC'
    and it will be disposed as soon as the GC
    comes along.
    Retaining the object for formal reasons would
    hinder it from being GC'd. Which is even worse.

    So to me there don't seem to be any truly
    critical implications at least.

    Concerning best practice it's probably common sense
    that return values should generally not be ignored
    and functions that return fully ignorable retvals should
    be refactored to void.
    Back in the days of C++ the most important issue
    linked to this subject was leaking memory.
    A function that return a 'new' object also returns the
    responsibility of deletion to the caller.
    So retaining the return value and taking care of
    was crucial sometimes in the pre-gc-days.

    Chris

     

    Monday, October 04, 2010 6:55 PM
  • I'm not aware of any modern language which forces you to assign the return value, so it's not just the C/C++ tradition.
    Convert between VB, C#, C++, & Java (http://www.tangiblesoftwaresolutions.com)
    Well PL/I and Ada insisted on this as does APL (I think) so there's three for starters. I persoanlly think it originated with C because I am not aware of any languges designed before C that allow this.
    Tuesday, October 05, 2010 2:53 AM
  • I am unhappy that C# has continued the tradition it inherited from C++ and C, of allowing a functions return value to be ignored by allowing callers to invoke functions as if they were methods. I think this is poor programming practice personally, C# enforces many sensible things but not this.

    A good case in point is if I invoke a function that returns me a disposable object but ignore (never refer to) the returned object reference.

    The method will create or obtain this object and return a reference to it, yet because it is ignored the caller will never call its Dispose method and so the object will have to be diposed of by the system, asynchronoulsy by the GC (unless it is disposed by some other thread or some other code).

    If the system's runtime was aware that a disposable object reference was returned but never assigned, I guess it could automatically call Dispose silently which would not be an invalid thing to do under the circumstances.

    But this is not trivial, because the functions return value could be implicitly used:

    SomeFunc(arg).SomeObjMethod(other_arg);

    Here the object ref returned by 'SomeFunc' is used but never retained, so we cannot dispose it, however it is used transiently to invoke 'SomeObjMethod' so cannot be automatically 'disposed' unless this is done after the completion of the entire statement...

    What do others think about this issue?

    Thanks

    Cap'n

     

     


    Well we are talking about two issues A) The ability to clean-up objects returned from method calls and B) the ability to disregard function return values. I agree with you that the LINQ example shows cases where we do not want to clean-up but there are times when one should and these are what I am talking about.

    I recall when I first started learning .Net and C#, being confused about "who" should destroy objects, and how we needed to worry about whether a method we call is creating an object or just passing back a ref to one that already exists.

    I always end up "hating" Dispose() because it is onlt because of this that the issue even comes up.

    Cap'n

    Tuesday, October 05, 2010 2:58 AM
  • I do think that the compiler (or Code Analysis) could warn you if you fail to assign an IDisposable return value to something (or use a "using"). That would give you lots of false positives, though, when a method returns something IDisposable which wasn't created by the method and therefore shouldn't necessarily be disposed by the caller.

    I've taken to returning IDisposable things via an "out" parameter to ensure that the user does something with them.

    What I would love to see is a compiler-enforced attribute that you could put onto methods that stated that calling code MUST do something with the return value. You would apply that attribute to your methods that create the IDisposable thing being returned.


    This is a great example of the kinds of pitfalls that are out there, I like the attribute idea.

    Cap'n

     

    Tuesday, October 05, 2010 2:59 AM
  • The return value of a function sometimes is not too important.
    For example think of a function that removes an element of a list/collection
    or whatsoever which also returns the removed element such as
    XmlNode.RemoveChild does.
    Probably in 9 of 10 cases you won't need the returned element.
    The return value is a goodie here. The method's core task is to
    remove child from the nodes childList.
    Another common example would be MessageBox.Show whose
    return value isn't to important if the box only exposes an OK-button.

    Forcing the caller to retain a reference which then is never used
    would be even worse language design, producing code-bloat and
    lots of unused, un-gc-able objects.
    So it is actually good and effective that we programmers decide
    which return values are of interest.

    Concerning the IDisposable-argument.
    Returning an IDisposable and not retaining it
    markes the object as 'targeted for GC'
    and it will be disposed as soon as the GC
    comes along.
    Retaining the object for formal reasons would
    hinder it from being GC'd. Which is even worse.

    So to me there don't seem to be any truly
    critical implications at least.

    Concerning best practice it's probably common sense
    that return values should generally not be ignored
    and functions that return fully ignorable retvals should
    be refactored to void.
    Back in the days of C++ the most important issue
    linked to this subject was leaking memory.
    A function that return a 'new' object also returns the
    responsibility of deletion to the caller.
    So retaining the return value and taking care of
    was crucial sometimes in the pre-gc-days.

    Chris

     


    Regarding your first example, I think such "optionally of interest" return values are adequately served by passing ref arguments, returning convenient little bits of info (common in C and Unix) like the removed element and so on can easily be acomplished that way.

    Being allowed to ignore the existence of a return value is no different to pretending that a function is actually a void method, but it isn't.

    Besides it is not so much ignioring the return value that bothers me, it is ignoring the fact that there is one, that I find to be at odds with everything we read about good programming these days - the invoke - return - value metaphor is an interface in reality.

    By forcing every returned value to be referenced (either implicitly as in LINQ or explicity via an assignment) our code would improve in readability, because we could code void methods that use ref arguments for those cases where the value wasn't always needed and actually return a value where we wanted to insist the caller use the returned value.

    Right now (As AW points out) a programmer cannot garunatee that a caller will use a returned value.

    Cap'n

    Tuesday, October 05, 2010 3:15 AM
  • Concerning the IDisposable-argument.
    Returning an IDisposable and not retaining it
    markes the object as 'targeted for GC'
    and it will be disposed as soon as the GC
    comes along.
    Retaining the object for formal reasons would
    hinder it from being GC'd. Which is even worse.

    So to me there don't seem to be any truly
    critical implications at least.

    What? You think that it's not critical to dispose things that are supposed to be disposed? Crikey!

    So what do you think the following code will do (assuming that a "C:\TEST" folder exists):

    using System;
    using System.IO;
    
    public class Demo
    {
      public static void Main()
      {
        File.CreateText("C:\\TEST\\TEST.TXT");
        File.CreateText("C:\\TEST\\TEST.TXT");
      }
    }
    
    

    Compared to:

    using System;
    using System.IO;
    
    public class Demo
    {
      public static void Main()
      {
        using (File.CreateText("C:\\TEST\\TEST.TXT"));
        using (File.CreateText("C:\\TEST\\TEST.TXT"));
      }
    }
    
    
    There are many instances of classes where it is absolutely critical to dispose their instances in a timely manner. Ignore this at your peril.

     

     

    Tuesday, October 05, 2010 8:47 AM
  • What? You think that it's not critical to dispose things that are supposed to be disposed? Crikey!

     

    Not as you handle a method which is meant to release unmanaged resources and his Idisposable interface as a method which disposes objects.

    Because that your father and mother have given you the name Matthew, does it not mean that everything you do is the same for all who have the name Matthew. 

    The same for the method name Dispose and the interface IDisposable, it is just a method name.

    Disposing of objects is done by the GC.


    Success
    Cor
    Tuesday, October 05, 2010 9:37 AM
  • because we could code void methods that use ref arguments for those cases where the value wasn't always needed and actually return a value where we wanted to insist the caller use the returned value.

    Actually it's the opposite. Having a byref parameter forces the caller to provide a variable to hold the returned value. You cannot ignore a byref parameter.
    Tuesday, October 05, 2010 10:24 AM
  • The two streamwriters will be disposed after Main
    has returned.
    If you'd keep the reference to streamwriters in two variables,
    they won't be disposed any sooner.
    So whats the point?

    Chris

    Tuesday, October 05, 2010 12:18 PM
  • The two streamwriters will be disposed after Main
    has returned.
    If you'd keep the reference to streamwriters in two variables,
    they won't be disposed any sooner.
    So whats the point?

    Chris

    Did you try running my sample code? Try it. Then you might see the point.

    Tuesday, October 05, 2010 2:52 PM
  • What? You think that it's not critical to dispose things that are supposed to be disposed? Crikey!

     

    Not as you handle a method which is meant to release unmanaged resources and his Idisposable interface as a method which disposes objects.

    Because that your father and mother have given you the name Matthew, does it not mean that everything you do is the same for all who have the name Matthew. 

    The same for the method name Dispose and the interface IDisposable, it is just a method name.

    Disposing of objects is done by the GC.


    Success
    Cor

    Disposing of unmanaged resources *may* be done by the GC, *if* someone implemented a finalize method. But such a finalizer will not be allowed to touch any managed resources.

    If one of the resources is critical, you'll be in a world of pain if you don't dispose it in a timely manner, especially if some other code wants to access the same resource shortly afterwards.

    I repeat my previous question; please have a go at answering it:

    What do you think this code will do?

    using System;
    using System.IO;

    public class Demo
    {
      public static void Main()
      {
        File.CreateText("C:\\TEST\\TEST.TXT");
        File.CreateText("C:\\TEST\\TEST.TXT");
      }
    }

    Seriously, you need to wise up about this kind of problem. There are many examples of people getting into trouble because they didn't dispose something. Here's a recent one:

    http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/72df3a7c-8b96-4e84-a9a6-6856f1b9f4d4

     

    Tuesday, October 05, 2010 2:55 PM
  • No i didn't run it. Probabaly the streamwriter's not disposed,
    and the 2nd call fails with the file handle still open.
    So that's really bad luck.

    Making the link back to the 'function return values should never be ignored' subject.
    Keeping a reference to an IDisposable returned by a function doesn't force anyone
    to explicitly dispose it, so there's merely nothing you gain by keeping it.

    Chris


    Tuesday, October 05, 2010 5:02 PM
  • Well PL/I and Ada insisted on this as does APL (I think) so there's three for starters. I persoanlly think it originated with C because I am not aware of any languges designed before C that allow this.
    Eiffel does as well. But then Ada is one of its influences.

    Kevin
    Tuesday, October 05, 2010 6:21 PM
  • No i didn't run it. Probabaly the streamwriter's not disposed,
    and the 2nd call fails with the file handle still open.
    So that's really bad luck.

    Making the link back to the 'function return values should never be ignored' subject.
    Keeping a reference to an IDisposable returned by a function doesn't force anyone
    to explicitly dispose it, so there's merely nothing you gain by keeping it.

    Chris



    That is not bad luck.  That's called lack of thorough coding. 

    Okay, let's say you don't gain anything.  But how much do you risk to lose?

    Rudy   =8^D


    Mark the best replies as answers. "Fooling computers since 1971."

    http://rudedog2.spaces.live.com/default.aspx

    Tuesday, October 05, 2010 6:28 PM
    Moderator
  • Sure it is bad luck.

    It is an stupid example that has got little
    to do with subject.
    It has got sth something  to do with subject
    why disposing can be crucial, especially disposing sth
    unmanged.
    As a reply to the initial statement it is still doesn't make much sense.
    Of course if you don't dispose sth u can get into trouble like this.
    The context however was that there are circumstances
    where you do not have to keep a reference to sth returned,
    even it is a IDisposable. Because it will be disposed sooner or later
    anyhow.
    Pretty often it doesn't matter if you let it be disposed by the GC.
    In the very impressive real-life demo where u open the same
    resource twice and run into an access violation, you have to care
    about disposing for sure - but that is still not reason enough
    to do so all the time and u can still safely let the GC to so work
    in many circumstances.

    So that's why I do not agree with your conclusions.

     

    Chris

     

    Tuesday, October 05, 2010 7:41 PM
  • because we could code void methods that use ref arguments for those cases where the value wasn't always needed and actually return a value where we wanted to insist the caller use the returned value.

    Actually it's the opposite. Having a byref parameter forces the caller to provide a variable to hold the returned value. You cannot ignore a byref parameter.


    You can in the sense that the caller is not compelled to manipulate the by ref argument when the called method returns, you just pass it in and either refer to it or ignore it, but it is visble to to you and anyone reading the code can see there is an information flow path.

    Cap'n

     

    Wednesday, October 06, 2010 1:33 AM
  • What? You think that it's not critical to dispose things that are supposed to be disposed? Crikey!

     

    Not as you handle a method which is meant to release unmanaged resources and his Idisposable interface as a method which disposes objects.

    Because that your father and mother have given you the name Matthew, does it not mean that everything you do is the same for all who have the name Matthew. 

    The same for the method name Dispose and the interface IDisposable, it is just a method name.

    Disposing of objects is done by the GC.


    Success
    Cor

    Disposing of unmanaged resources *may* be done by the GC, *if* someone implemented a finalize method. But such a finalizer will not be allowed to touch any managed resources.

    If one of the resources is critical, you'll be in a world of pain if you don't dispose it in a timely manner, especially if some other code wants to access the same resource shortly afterwards.

    I repeat my previous question; please have a go at answering it:

    What do you think this code will do?

    using System;
    using System.IO;

    public class Demo
    {
      public static void Main()
      {
        File.CreateText("C:\\TEST\\TEST.TXT");
        File.CreateText("C:\\TEST\\TEST.TXT");
      }
    }

    Seriously, you need to wise up about this kind of problem. There are many examples of people getting into trouble because they didn't dispose something. Here's a recent one:

    http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/72df3a7c-8b96-4e84-a9a6-6856f1b9f4d4

     


    MW is 100% correct, the GC runs asynchronously at indeterminate times, and is non intuitive. Besides the GC alone won't help when an object has references to native/unmanaged resources, because these must be closed/detached etc explicitly. We have a system here that aquires/release "handles" to system resources (a proprietary fast BD) sometimes hundreds of times/second and we need to ensure that Dispose() is called as soon as is practical.

    I just wish the CLR was better at this, and would allow us to forget about it !

    Cap'n

     

    Wednesday, October 06, 2010 1:39 AM
  • Sure it is bad luck.

    It is an stupid example that has got little
    to do with subject.
    It has got sth something  to do with subject
    why disposing can be crucial, especially disposing sth
    unmanged.
    As a reply to the initial statement it is still doesn't make much sense.
    Of course if you don't dispose sth u can get into trouble like this.
    The context however was that there are circumstances
    where you do not have to keep a reference to sth returned,
    even it is a IDisposable. Because it will be disposed sooner or later
    anyhow.
    Pretty often it doesn't matter if you let it be disposed by the GC.
    In the very impressive real-life demo where u open the same
    resource twice and run into an access violation, you have to care
    about disposing for sure - but that is still not reason enough
    to do so all the time and u can still safely let the GC to so work
    in many circumstances.

    So that's why I do not agree with your conclusions.

     

    Chris

     


    But what about factory methods that create objects? We have a system here and we have a class called "Dir" (similar to a disk folder but memory based). A Dir has many methods, one being GetDir to get a sub directorym this method returns a Dir object. So one can code:

    Dir directory;

    directory = Root.GetDir("Base").GetDir("Servers").GetDir("Primary");

    Each "GetDir" creates and returns a "Dir" object, that object encapsulates a "handle" (similar to an OS handle) which is used internally to control shared operations (e.g. preventing a Dir being deleted if it is in use and so on).

    Now the second and third calls to GetDir above, return a Dir object, but it isn't assigned to a variable, so we cannot call Dispose() BUT we want to call Dispose() as soon as we are done for all kinds of reasons.

    The only way to do what we want is to laboriously call each GetDir and assign its return value to some temp Dir instance, and then call Dispose() on each of these when we are done, we cannot code it as shown above else we cannot reliably Dispose() in a timely manner.

    I find this kind of concern/worry extremely troublesome for large complex systems.

    Cap'n

     

    Wednesday, October 06, 2010 1:50 AM
  • > allowing a functions return value to be ignored by allowing callers

    Suppoes the method returns an object and the compiler forces you to make use of the result.  Suppose the returned object has 4 properties, one of which is "really important".  Suppose the caller gets the value of 3 of the 4 properties, but not the "really important" one.  So your feature does not buy you much: the caller can still ignore something "important".

    Java has something similar where a method can declare that it can throw a so-called "checked" type of exception.  This forces the caller to catch or rethrow exceptions of that type.  The .NET architects considered and rejected this approach.  There seem to be no perfect solutions, only tradeoffs.

    > I guess it could automatically call Dispose silently which would not be an invalid thing to do under the circumstances.

    Actually, it might be invalid.  The method you called may have established a path between a surviving GC root and the returned object.  For example, in addition to returning the object it might have also added it to a cache.  The compiler cannot know this has happened in general.

     

    Wednesday, October 06, 2010 2:21 AM
  • Sure it is bad luck.

    It is an stupid example that has got little
    to do with subject.
    It has got sth something  to do with subject
    why disposing can be crucial, especially disposing sth
    unmanged.
    As a reply to the initial statement it is still doesn't make much sense.
    Of course if you don't dispose sth u can get into trouble like this.
    The context however was that there are circumstances
    where you do not have to keep a reference to sth returned,
    even it is a IDisposable. Because it will be disposed sooner or later
    anyhow.
    Pretty often it doesn't matter if you let it be disposed by the GC.
    In the very impressive real-life demo where u open the same
    resource twice and run into an access violation, you have to care
    about disposing for sure - but that is still not reason enough
    to do so all the time and u can still safely let the GC to so work
    in many circumstances.

    So that's why I do not agree with your conclusions.

     

    Chris

     

    It's not bad luck, it's bad programming. Are you saying that this is the way you program? You didn't even know that it would cause a problem, and originally asked "what's the point?". Now you say "Of course if you don't dispose sth u can get into trouble like this"...

    As to your not agreeing with my conclusions: Did you even read my original response?

    If so, which part of this did you disagree with:

    "What I would love to see is a compiler-enforced attribute that you could put onto methods that stated that calling code MUST do something with the return value. You would apply that attribute to your methods that create the IDisposable thing being returned."

    Wednesday, October 06, 2010 8:47 AM
  • > allowing a functions return value to be ignored by allowing callers

    Suppoes the method returns an object and the compiler forces you to make use of the result.  Suppose the returned object has 4 properties, one of which is "really important".  Suppose the caller gets the value of 3 of the 4 properties, but not the "really important" one.  So your feature does not buy you much: the caller can still ignore something "important".

    Java has something similar where a method can declare that it can throw a so-called "checked" type of exception.  This forces the caller to catch or rethrow exceptions of that type.  The .NET architects considered and rejected this approach.  There seem to be no perfect solutions, only tradeoffs.

    > I guess it could automatically call Dispose silently which would not be an invalid thing to do under the circumstances.

    Actually, it might be invalid.  The method you called may have established a path between a surviving GC root and the returned object.  For example, in addition to returning the object it might have also added it to a cache.  The compiler cannot know this has happened in general.

     


    The usual response to this kind of comment is "There is no greater fool than he who did nothing because he could do so little." Or alternatively "Suppose my brother was a girl. Then he'd be my sister!". :)

    Yes, you have to work to ensure that the caller at least does something with a returned value. The problem was so bad with C/C++ functions returning error values that they invented exceptions to deal with the problem!

    One solution, as I outlined above, is to use 'out' parameters for things that must not be ignored. (The only things that normally must not be ignored are error messages - now handled with exceptions - and things that must be disposed.)

    What we do is for the DEBUG (not release) versions of a finalizer (or Dispose(bool) called with a false value) for a class that MUST be disposed is to display a message box complaining about the fact that Dispose() wasn't called.

    Two examples of our classes that MUST be disposed are:

    (1) A class that represents a floating license acquired to enable the user to run some function in our software. If that license was not released, it means another user could not use it until the garbage collector runs.

    (2) A class that encapsulates a lock on a database record, preventing other users from editing it.

    The code that we use to display the error message looks like this. Note the code that prevents the message box being displayed if we're running a unit test (for obvious reasons):

    protected override void Dispose(bool disposing)
    {
      if (!_isDisposed)
      {
        if (disposing)
        {
          _isDisposed = true;
          // Rest of normal dispose logic here.
        }
        else // Called from finalizer because nobody called Dispose().
        {
          #if DEBUG  // Don't laden the release version with this.
    
          string message = this.GetType().FullName + " wasn't disposed properly.";
          Debug.WriteLine(message);
    
          bool isRunningUnitTest = (Process.GetCurrentProcess().ProcessName == "VSTestHost");
    
          if (Environment.UserInteractive && !isRunningUnitTest)
          {
            MessageBox.Show   // Disposing this properly is important enough to display an error message!
            (          // Otherwise some streams will be left open, which would be a bad thing...
              message,
              Application.ProductName + " - Diagnostic",
              MessageBoxButtons.OK,
              MessageBoxIcon.Information,
              MessageBoxDefaultButton.Button1,
              MessageBoxOptions.DefaultDesktopOnly // This prevents the message from disappearing as the process closes.
            );
          }
    
          #endif
        }
      }
    }
    
    
    It will always be necessary to include such diagnostics I think, because you can never force callers to dispose things. All you can do is mitigate things (ideally through the use of special attributes that you can apply to factory methods, for example, but for now "out" parameters will have to do).

     

    Wednesday, October 06, 2010 9:04 AM
  • Sure it is bad luck.

    It is an stupid example that has got little
    to do with subject.

    If you think it's a "stupid example that has little to do with the subject", then you didn't read the OP properly.

    The OP explicitly mentions the need to dispose returned values from some methods, and my sample code shows a good example of why.

    No-one would write code like that in real life, but what I have seen more than once is someone creating a file in one method, and then immediately calling another method to process that file. Because they forgot to call dispose in the creation method, the processing method threw an access violation.

     

    Wednesday, October 06, 2010 9:19 AM
  • You can in the sense that the caller is not compelled to manipulate the by ref argument when the called method returns, you just pass it in and either refer to it or ignore it, but it is visble to to you and anyone reading the code can see there is an information flow path.

    If that's your definition of "can ignore a byref parameter", then I don't see why the use of a byref parameter would be useful "for those cases where the value wasn't always needed" and what would be gained by having the compiler force the caller to put the return value somewhere.
    Wednesday, October 06, 2010 2:23 PM
  • You can in the sense that the caller is not compelled to manipulate the by ref argument when the called method returns, you just pass it in and either refer to it or ignore it, but it is visble to to you and anyone reading the code can see there is an information flow path.

    If that's your definition of "can ignore a byref parameter", then I don't see why the use of a byref parameter would be useful "for those cases where the value wasn't always needed" and what would be gained by having the compiler force the caller to put the return value somewhere.


    Well I've thought about this some more and I think MW has a good idea with attributes. They could introduce a new attribute that we can specify for a function in a class. Like "[AutoDispose]" or something. Then they could improve the compilers so that if such a function is invoked AND the returned reference is not assigned (or passed into another method) by the caller to some other variable (easy for compiler to detect) AND the reference returned by the function, implements Dispose, then automatically call Dispose AFTER the entire statement has executed.

    Then we could decorate methods with that as we see fit and know that any callers that "ignore" the returned reference, will automatically dispose of the reference no matter what.

    This way the designer/coder could add that attribute to methods that create new objects and omit the attribute from methods that just return an already existing object.

    Thoughts?

    Cap'n

     

     

    Monday, October 11, 2010 1:39 PM
  • Attributes that affect compiler behavior really do sound like a good idea.  But I think it would represent a dramatic departure.  Something to be avoided for a language such as C#.  The idea really amounts to compiler directives, which are conspicously absent from the language.

     Attributes are intended for run time use, not compile time use.


    Mark the best replies as answers. "Fooling computers since 1971."

    http://rudedog2.spaces.live.com/default.aspx

    Monday, October 11, 2010 5:04 PM
    Moderator
  • Attributes are intended for run time use, not compile time use.

    Except those which are used exclusively by the compiler: MethodImpl, IndexerName. Those checked by the compiler to allow or disallow compilation: AttributeUsage, Obsolete, CLSCompliant. Those changing the way the code is compiled: Conditional.

    Attributes defined by the user are intended for runtime use.

    The number of attributes used at compile-time suggests that there isn't such a restriction on attributes defined by the C# specification or by the Microsoft C# compiler implementation. An AutoDispose would fall in that category.

    Monday, October 11, 2010 9:21 PM
  • > Then they could improve the compilers so that if such a function is invoked AND the returned reference is not assigned (or passed into another method) by the caller to some other variable (easy for compiler to detect) AND the reference returned by the function, implements Dispose, then automatically call Dispose AFTER the entire statement has executed.

    I think the problem is that there would be no feedback as to whether the compiler has inserted a Dispose for you or not.  The set of conditions under which it would do so are not obvious.  Might as well make it an error and force you to respond to the error by either calling Dispose or tell the compiler "I know what I'm doing".  Various versions of FxCop have tried to find missing Dispose calls...  So there is some promise in the static code checking area.  But IMHO don't think an automatic Dispose feature is a "winner".

    There are reports posted on the Internet that when .NET was ordinally developed, the issues surrounding Dispose were considered in depth.  I think we got something reasonable and relatively simple out of them.

     

     

    Wednesday, October 13, 2010 12:09 AM
  • Btw, the C++/CLI compiler implements a autodispose mechanism for
    managed resources by automatically adding IDispose to any ref class
    and calling Dispose in the Finalizer of the object.

    In C# you have FxCop to make you implement the same logic.

    Chris
    Wednesday, October 13, 2010 1:08 AM
  • > and calling Dispose in the Finalizer of the object.

    Do you mean it calls Dispose(false)?  That would be called the "dispose pattern".  When Dispose(boolean) is properly implemented, it disposes only unmanaged resources since those are the only ones that are safe to dispose from a finalizer.  This pattern is often implemented in other .NET languages too by coding the finalizer.  However, it cannot validly do the full-blown Dispose(true) kind of dispose which is undoubtedly what the others on this thread want.

    Also note that the finalizer runs at the GC's whim.  Not soon after the method that uses the object ends as the others seem to want too.

     

    Wednesday, October 13, 2010 1:46 AM
  • Yes exactelly the C++/CLI compiler autoimplements this pattern
    for ref classes, even if it the class doesn't implement IDispose explicitly.

    It calls Dispose(false) in Finalize and Dispose(true) in Dispose itself.
    Where the destructors implementation becomes Dispose().
    Of course unmanged resources will only be released by explicitly
    deleting the 'handle' (which calls the destructor, which calls Dispose(true))
    - if properly implemented.

    Its explained in this blog: C++/CLI, IDisposable and Finalize

    So unmanaged stuff cannot and should not be gc'ed.

    Chris

     

    Wednesday, October 13, 2010 3:22 AM